@devioarts/capacitor-mdns 0.0.2 → 0.1.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/Package.swift +1 -1
- package/README.md +54 -67
- package/android/build.gradle +11 -11
- package/android/src/main/AndroidManifest.xml +2 -0
- package/android/src/main/java/com/devioarts/capacitor/mdns/mDNS.kt +217 -51
- package/android/src/main/java/com/devioarts/capacitor/mdns/mDNSPlugin.kt +20 -9
- package/dist/docs.json +65 -3
- package/dist/esm/definitions.d.ts +28 -2
- package/dist/esm/definitions.js.map +1 -1
- package/dist/esm/index.js +1 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/web.d.ts +3 -1
- package/dist/esm/web.js +12 -3
- package/dist/esm/web.js.map +1 -1
- package/dist/plugin.cjs.js +13 -3
- package/dist/plugin.cjs.js.map +1 -1
- package/dist/plugin.js +13 -3
- package/dist/plugin.js.map +1 -1
- package/docs/electron.md +65 -0
- package/docs/platform-setup.md +52 -0
- package/docs/playground.md +19 -0
- package/docs/runtime-behavior.md +14 -0
- package/electron/dist/plugin-settings.js +15 -0
- package/electron/dist/plugin-settings.js.map +1 -0
- package/electron/dist/plugin.cjs.js +344 -0
- package/electron/dist/plugin.cjs.js.map +1 -0
- package/electron/global.d.ts +2 -0
- package/electron/mdns-bridge.cjs +9 -4
- package/electron/mdns.ts +151 -63
- package/electron/rollup.config.mjs +22 -0
- package/electron/src/index.ts +1 -0
- package/electron/src/plugin-settings.ts +12 -0
- package/electron/tsconfig.json +21 -0
- package/electron/types-public/index.d.ts +25 -0
- package/ios/Sources/mDNSPlugin/mDNS.swift +95 -28
- package/ios/Sources/mDNSPlugin/mDNSPlugin.swift +12 -3
- package/ios/Tests/mDNSPluginTests/mDNSPluginTests.swift +3 -9
- package/package.json +47 -22
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Playground
|
|
2
|
+
|
|
3
|
+
The `playground` directory is the maintained example app for this package.
|
|
4
|
+
|
|
5
|
+
It demonstrates:
|
|
6
|
+
|
|
7
|
+
- starting and stopping an mDNS advertisement;
|
|
8
|
+
- discovering services by type and optional name;
|
|
9
|
+
- using the Electron preload bridge;
|
|
10
|
+
- checking `getPluginPlatform()` so you can confirm which runtime implementation handled a call.
|
|
11
|
+
|
|
12
|
+
Run it from the playground directory:
|
|
13
|
+
|
|
14
|
+
```shell
|
|
15
|
+
npm install
|
|
16
|
+
npm run dev
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
For Electron, use the playground together with `devioarts/capacitor-electron`.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# Runtime behavior
|
|
2
|
+
|
|
3
|
+
- All methods resolve with the documented result shape. Runtime failures are reported through
|
|
4
|
+
`error` and `errorMessage` instead of rejecting when the platform bridge can recover safely.
|
|
5
|
+
- `getPluginPlatform()` resolves to `ios`, `android`, `electron`, or `web` from the implementation
|
|
6
|
+
that handled the call.
|
|
7
|
+
- `startBroadcast()` is guarded by a native timeout on Android, iOS, and Electron. If the OS does
|
|
8
|
+
not report publish success or failure, the operation is stopped and returned as an error.
|
|
9
|
+
- Only one advertisement is active at a time. Starting a new advertisement stops the previous one.
|
|
10
|
+
- Discovery is timeboxed and cleans up native listeners, browsers, service-info callbacks, and
|
|
11
|
+
resolvers after completion. Overlapping discovery calls are serialized or safely replace the
|
|
12
|
+
previous native session so stale callbacks cannot complete a newer request.
|
|
13
|
+
- `stopBroadcast()` is idempotent and safe to call repeatedly, including after failed or timed-out
|
|
14
|
+
publish attempts.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Metadata consumed by the capacitor-electron runtime generator (`npm run update`).
|
|
5
|
+
*
|
|
6
|
+
* Import path for the JS layer: `@devioarts/capacitor-mdns/electron/settings`.
|
|
7
|
+
*/
|
|
8
|
+
const pluginSettings = {
|
|
9
|
+
pluginClass: 'mDNS',
|
|
10
|
+
pluginMethods: ['getPluginPlatform', 'startBroadcast', 'stopBroadcast', 'discover'],
|
|
11
|
+
pluginEvents: [],
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
exports.pluginSettings = pluginSettings;
|
|
15
|
+
//# sourceMappingURL=plugin-settings.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin-settings.js","sources":["../build/electron/src/plugin-settings.js"],"sourcesContent":["/**\n * Metadata consumed by the capacitor-electron runtime generator (`npm run update`).\n *\n * Import path for the JS layer: `@devioarts/capacitor-mdns/electron/settings`.\n */\nexport const pluginSettings = {\n pluginClass: 'mDNS',\n pluginMethods: ['getPluginPlatform', 'startBroadcast', 'stopBroadcast', 'discover'],\n pluginEvents: [],\n};\n//# sourceMappingURL=plugin-settings.js.map"],"names":[],"mappings":";;AAAA;AACA;AACA;AACA;AACA;AACY,MAAC,cAAc,GAAG;AAC9B,IAAI,WAAW,EAAE,MAAM;AACvB,IAAI,aAAa,EAAE,CAAC,mBAAmB,EAAE,gBAAgB,EAAE,eAAe,EAAE,UAAU,CAAC;AACvF,IAAI,YAAY,EAAE,EAAE;AACpB;;;;"}
|
|
@@ -0,0 +1,344 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var Bonjour = require('bonjour-service');
|
|
4
|
+
var electron = require('electron');
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Electron main-process implementation of the mDNS/Bonjour functionality.
|
|
8
|
+
*
|
|
9
|
+
* Uses the `bonjour-service` package to:
|
|
10
|
+
* - publish (advertise) a single service;
|
|
11
|
+
* - discover services of a given type and normalize results to the shared schema;
|
|
12
|
+
* - wire the API over Electron's ipcMain (see registerIpc/attachOnReady).
|
|
13
|
+
*
|
|
14
|
+
* Notes:
|
|
15
|
+
* - Instance name matching is normalized and prefix-safe, mirroring iOS/Android behavior.
|
|
16
|
+
* - TXT records are forwarded as strings when present.
|
|
17
|
+
*/
|
|
18
|
+
class mDNS {
|
|
19
|
+
constructor() {
|
|
20
|
+
this.publishTimeoutMs = 5000;
|
|
21
|
+
this.stopTimeoutMs = 3000;
|
|
22
|
+
this.broadcastQueue = Promise.resolve();
|
|
23
|
+
this.destroyed = false;
|
|
24
|
+
//<editor-fold desc="Init/Destroy">
|
|
25
|
+
this.ipcRegistered = false;
|
|
26
|
+
//</editor-fold>
|
|
27
|
+
this.bonjour = new Bonjour();
|
|
28
|
+
}
|
|
29
|
+
registerIpc() {
|
|
30
|
+
if (this.ipcRegistered)
|
|
31
|
+
return;
|
|
32
|
+
try {
|
|
33
|
+
electron.ipcMain.removeHandler('mdns:startBroadcast');
|
|
34
|
+
electron.ipcMain.removeHandler('mdns:stopBroadcast');
|
|
35
|
+
electron.ipcMain.removeHandler('mdns:discover');
|
|
36
|
+
electron.ipcMain.removeHandler('mdns:getPluginPlatform');
|
|
37
|
+
}
|
|
38
|
+
catch (_a) {
|
|
39
|
+
/* ignore */
|
|
40
|
+
}
|
|
41
|
+
electron.ipcMain.handle('mdns:startBroadcast', (_evt, o) => this.startBroadcast(o));
|
|
42
|
+
electron.ipcMain.handle('mdns:stopBroadcast', () => this.stopBroadcast());
|
|
43
|
+
electron.ipcMain.handle('mdns:discover', (_evt, o) => this.discover(o));
|
|
44
|
+
electron.ipcMain.handle('mdns:getPluginPlatform', () => this.getPluginPlatform());
|
|
45
|
+
this.ipcRegistered = true;
|
|
46
|
+
}
|
|
47
|
+
unregisterIpc() {
|
|
48
|
+
if (!this.ipcRegistered)
|
|
49
|
+
return;
|
|
50
|
+
try {
|
|
51
|
+
electron.ipcMain.removeHandler('mdns:startBroadcast');
|
|
52
|
+
electron.ipcMain.removeHandler('mdns:stopBroadcast');
|
|
53
|
+
electron.ipcMain.removeHandler('mdns:discover');
|
|
54
|
+
electron.ipcMain.removeHandler('mdns:getPluginPlatform');
|
|
55
|
+
}
|
|
56
|
+
catch (_a) {
|
|
57
|
+
/* ignore */
|
|
58
|
+
}
|
|
59
|
+
this.ipcRegistered = false;
|
|
60
|
+
}
|
|
61
|
+
/** Manual IPC registration (if you set autoRegisterIpc: false). Idempotent. */
|
|
62
|
+
init() {
|
|
63
|
+
this.registerIpc();
|
|
64
|
+
}
|
|
65
|
+
async destroy() {
|
|
66
|
+
this.destroyed = true;
|
|
67
|
+
this.unregisterIpc();
|
|
68
|
+
await this.withBroadcastLock(async () => {
|
|
69
|
+
await this.stopBroadcastUnlocked();
|
|
70
|
+
try {
|
|
71
|
+
this.bonjour.destroy();
|
|
72
|
+
}
|
|
73
|
+
catch (err) {
|
|
74
|
+
console.warn('[mDNS] bonjour.destroy error:', err);
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
// ----------------------------- utils -----------------------------
|
|
79
|
+
toErr(err) {
|
|
80
|
+
return err instanceof Error ? err.message : String(err);
|
|
81
|
+
}
|
|
82
|
+
validatePort(port) {
|
|
83
|
+
return Number.isInteger(port) && typeof port === 'number' && port > 0 && port <= 65535
|
|
84
|
+
? null
|
|
85
|
+
: 'Missing/invalid port';
|
|
86
|
+
}
|
|
87
|
+
isRecord(value) {
|
|
88
|
+
return !!value && typeof value === 'object' && !Array.isArray(value);
|
|
89
|
+
}
|
|
90
|
+
withBroadcastLock(work) {
|
|
91
|
+
// Publish and stop share one Bonjour service; serializing them prevents orphaned advertisers.
|
|
92
|
+
const run = this.broadcastQueue.catch(() => undefined).then(work);
|
|
93
|
+
this.broadcastQueue = run.catch(() => undefined);
|
|
94
|
+
return run;
|
|
95
|
+
}
|
|
96
|
+
normalize(name) {
|
|
97
|
+
return name.replace(/ \(\d+\)$/, '');
|
|
98
|
+
}
|
|
99
|
+
matchesTarget(candidate, target) {
|
|
100
|
+
if (!target)
|
|
101
|
+
return true;
|
|
102
|
+
const c = this.normalize(candidate), t = this.normalize(target);
|
|
103
|
+
return c === t || c.startsWith(t);
|
|
104
|
+
}
|
|
105
|
+
parseType(typeWithDot) {
|
|
106
|
+
const raw = typeof typeWithDot === 'string' && typeWithDot.trim() ? typeWithDot.trim() : '_http._tcp.';
|
|
107
|
+
const s = raw.replace(/\.$/, '');
|
|
108
|
+
const m = /^_([^.]+)\._(tcp|udp)$/.exec(s);
|
|
109
|
+
if (!m)
|
|
110
|
+
return { type: 'http', protocol: 'tcp' };
|
|
111
|
+
return { type: m[1], protocol: m[2] };
|
|
112
|
+
}
|
|
113
|
+
toFullType(type, protocol) {
|
|
114
|
+
return `_${type}._${protocol}.`;
|
|
115
|
+
}
|
|
116
|
+
hasCbStop(x) {
|
|
117
|
+
return !!x && typeof x.stop === 'function';
|
|
118
|
+
}
|
|
119
|
+
async safeStopService(svc) {
|
|
120
|
+
if (!svc || !this.hasCbStop(svc))
|
|
121
|
+
return;
|
|
122
|
+
try {
|
|
123
|
+
await new Promise((res) => {
|
|
124
|
+
let settled = false;
|
|
125
|
+
const done = () => {
|
|
126
|
+
if (settled)
|
|
127
|
+
return;
|
|
128
|
+
settled = true;
|
|
129
|
+
if (timeout)
|
|
130
|
+
clearTimeout(timeout);
|
|
131
|
+
res();
|
|
132
|
+
};
|
|
133
|
+
const timeout = setTimeout(done, this.stopTimeoutMs);
|
|
134
|
+
try {
|
|
135
|
+
svc.stop(done);
|
|
136
|
+
}
|
|
137
|
+
catch (e) {
|
|
138
|
+
console.warn('[mDNS] service.stop threw:', e);
|
|
139
|
+
done();
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
catch (err) {
|
|
144
|
+
console.warn('[mDNS] service.stop error:', err);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
safeStopBrowser(b) {
|
|
148
|
+
if (!b)
|
|
149
|
+
return;
|
|
150
|
+
try {
|
|
151
|
+
b.stop();
|
|
152
|
+
}
|
|
153
|
+
catch (err) {
|
|
154
|
+
console.warn('[mDNS] browser.stop error:', err);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
// ----------------------------- API -----------------------------
|
|
158
|
+
/**
|
|
159
|
+
* Return the Electron main-process implementation marker.
|
|
160
|
+
*/
|
|
161
|
+
async getPluginPlatform() {
|
|
162
|
+
return { platform: 'electron' };
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Publish (advertise) a single Bonjour/mDNS service via bonjour-service.
|
|
166
|
+
* @param options See MdnsBroadcastOptions for type/name/port/txt.
|
|
167
|
+
* @returns Result indicating whether publishing is active and the final name.
|
|
168
|
+
*/
|
|
169
|
+
async startBroadcast(options) {
|
|
170
|
+
return this.withBroadcastLock(async () => {
|
|
171
|
+
const safeOptions = (options !== null && options !== void 0 ? options : {});
|
|
172
|
+
const portError = this.validatePort(safeOptions.port);
|
|
173
|
+
if (portError)
|
|
174
|
+
return { publishing: false, name: '', error: true, errorMessage: portError };
|
|
175
|
+
if (this.destroyed)
|
|
176
|
+
return { publishing: false, name: '', error: true, errorMessage: 'mDNS instance is destroyed' };
|
|
177
|
+
await this.stopBroadcastUnlocked();
|
|
178
|
+
const { type, protocol } = this.parseType(safeOptions.type);
|
|
179
|
+
return new Promise((resolve) => {
|
|
180
|
+
let settled = false;
|
|
181
|
+
let timeout = null;
|
|
182
|
+
const safeResolve = (r) => {
|
|
183
|
+
if (!settled) {
|
|
184
|
+
settled = true;
|
|
185
|
+
if (timeout) {
|
|
186
|
+
clearTimeout(timeout);
|
|
187
|
+
timeout = null;
|
|
188
|
+
}
|
|
189
|
+
resolve(r);
|
|
190
|
+
}
|
|
191
|
+
};
|
|
192
|
+
try {
|
|
193
|
+
const svc = this.bonjour.publish({
|
|
194
|
+
name: typeof safeOptions.name === 'string' && safeOptions.name.trim()
|
|
195
|
+
? safeOptions.name.trim()
|
|
196
|
+
: 'DevIOArtsMDNS',
|
|
197
|
+
type,
|
|
198
|
+
protocol,
|
|
199
|
+
port: safeOptions.port,
|
|
200
|
+
txt: this.isRecord(safeOptions.txt) ? this.normalizeTxt(safeOptions.txt) : undefined,
|
|
201
|
+
});
|
|
202
|
+
const cleanupListeners = () => {
|
|
203
|
+
try {
|
|
204
|
+
svc.removeListener('up', onUp);
|
|
205
|
+
svc.removeListener('error', onError);
|
|
206
|
+
}
|
|
207
|
+
catch (_a) {
|
|
208
|
+
/* ignore */
|
|
209
|
+
}
|
|
210
|
+
};
|
|
211
|
+
const onUp = () => {
|
|
212
|
+
cleanupListeners();
|
|
213
|
+
safeResolve({ publishing: true, name: svc.name || '', error: false, errorMessage: null });
|
|
214
|
+
};
|
|
215
|
+
const onError = (err) => {
|
|
216
|
+
cleanupListeners();
|
|
217
|
+
void this.safeStopService(svc);
|
|
218
|
+
if (this.advertiser === svc)
|
|
219
|
+
this.advertiser = undefined;
|
|
220
|
+
safeResolve({ publishing: false, name: '', error: true, errorMessage: this.toErr(err) });
|
|
221
|
+
};
|
|
222
|
+
const onTimeout = () => {
|
|
223
|
+
cleanupListeners();
|
|
224
|
+
void this.safeStopService(svc);
|
|
225
|
+
if (this.advertiser === svc)
|
|
226
|
+
this.advertiser = undefined;
|
|
227
|
+
safeResolve({
|
|
228
|
+
publishing: false,
|
|
229
|
+
name: '',
|
|
230
|
+
error: true,
|
|
231
|
+
errorMessage: `Timed out waiting for service publish after ${this.publishTimeoutMs}ms`,
|
|
232
|
+
});
|
|
233
|
+
};
|
|
234
|
+
svc.once('up', onUp);
|
|
235
|
+
svc.once('error', onError);
|
|
236
|
+
timeout = setTimeout(onTimeout, this.publishTimeoutMs);
|
|
237
|
+
this.advertiser = svc;
|
|
238
|
+
}
|
|
239
|
+
catch (e) {
|
|
240
|
+
safeResolve({ publishing: false, name: '', error: true, errorMessage: this.toErr(e) });
|
|
241
|
+
}
|
|
242
|
+
});
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Stop advertising the current service if any and clear internal state.
|
|
247
|
+
* @returns Result indicating whether the advertiser is active and error info.
|
|
248
|
+
*/
|
|
249
|
+
async stopBroadcast() {
|
|
250
|
+
return this.withBroadcastLock(() => this.stopBroadcastUnlocked());
|
|
251
|
+
}
|
|
252
|
+
async stopBroadcastUnlocked() {
|
|
253
|
+
try {
|
|
254
|
+
if (this.advertiser) {
|
|
255
|
+
await this.safeStopService(this.advertiser);
|
|
256
|
+
this.advertiser = undefined;
|
|
257
|
+
}
|
|
258
|
+
return { publishing: false, error: false, errorMessage: null };
|
|
259
|
+
}
|
|
260
|
+
catch (e) {
|
|
261
|
+
return { publishing: false, error: true, errorMessage: this.toErr(e) };
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* Discover services of the given type and optionally filter by instance name.
|
|
266
|
+
* Deduplicates by (name:port), collects IPv4/IPv6 addresses and TXT, and
|
|
267
|
+
* resolves with either an early-exit match or after a timeout.
|
|
268
|
+
* @param options See MdnsDiscoverOptions for type/name/timeout.
|
|
269
|
+
*/
|
|
270
|
+
async discover(options = {}) {
|
|
271
|
+
const safeOptions = (options !== null && options !== void 0 ? options : {});
|
|
272
|
+
if (this.destroyed) {
|
|
273
|
+
return { error: true, errorMessage: 'mDNS instance is destroyed', servicesFound: 0, services: [] };
|
|
274
|
+
}
|
|
275
|
+
const { type, protocol } = this.parseType(safeOptions.type);
|
|
276
|
+
const targetId = typeof safeOptions.name === 'string' && safeOptions.name ? safeOptions.name : null;
|
|
277
|
+
const timeoutMs = typeof safeOptions.timeout === 'number' ? safeOptions.timeout : 3000;
|
|
278
|
+
let browser = null;
|
|
279
|
+
const services = [];
|
|
280
|
+
let hadError = false;
|
|
281
|
+
let errMsg = null;
|
|
282
|
+
return new Promise((resolve) => {
|
|
283
|
+
let timer = null;
|
|
284
|
+
let settled = false;
|
|
285
|
+
const finish = () => {
|
|
286
|
+
if (settled)
|
|
287
|
+
return;
|
|
288
|
+
settled = true;
|
|
289
|
+
if (browser) {
|
|
290
|
+
this.safeStopBrowser(browser);
|
|
291
|
+
browser = null;
|
|
292
|
+
}
|
|
293
|
+
if (timer) {
|
|
294
|
+
clearTimeout(timer);
|
|
295
|
+
timer = null;
|
|
296
|
+
}
|
|
297
|
+
resolve({
|
|
298
|
+
error: hadError,
|
|
299
|
+
errorMessage: errMsg,
|
|
300
|
+
services,
|
|
301
|
+
servicesFound: services.length,
|
|
302
|
+
});
|
|
303
|
+
};
|
|
304
|
+
try {
|
|
305
|
+
browser = this.bonjour.find({ type, protocol }, (s) => {
|
|
306
|
+
var _a;
|
|
307
|
+
if (!this.matchesTarget(s.name || '', targetId))
|
|
308
|
+
return;
|
|
309
|
+
const item = {
|
|
310
|
+
name: s.name || '',
|
|
311
|
+
type: this.toFullType(type, protocol),
|
|
312
|
+
domain: 'local.',
|
|
313
|
+
port: (_a = s.port) !== null && _a !== void 0 ? _a : 0,
|
|
314
|
+
hosts: Array.isArray(s.addresses) ? s.addresses.slice() : [],
|
|
315
|
+
txt: s.txt && Object.keys(s.txt).length ? this.normalizeTxt(s.txt) : undefined,
|
|
316
|
+
};
|
|
317
|
+
const key = `${item.name}:${item.port}`;
|
|
318
|
+
if (!services.some((x) => `${x.name}:${x.port}` === key))
|
|
319
|
+
services.push(item);
|
|
320
|
+
if (targetId && this.matchesTarget(item.name, targetId))
|
|
321
|
+
finish();
|
|
322
|
+
});
|
|
323
|
+
// Record error and let the timeout conclude; results will still be returned.
|
|
324
|
+
const onBrowserError = (err) => {
|
|
325
|
+
hadError = true;
|
|
326
|
+
errMsg = this.toErr(err);
|
|
327
|
+
};
|
|
328
|
+
browser.on('error', onBrowserError);
|
|
329
|
+
timer = setTimeout(finish, Math.max(0, timeoutMs));
|
|
330
|
+
}
|
|
331
|
+
catch (err) {
|
|
332
|
+
hadError = true;
|
|
333
|
+
errMsg = this.toErr(err);
|
|
334
|
+
finish();
|
|
335
|
+
}
|
|
336
|
+
});
|
|
337
|
+
}
|
|
338
|
+
normalizeTxt(txt) {
|
|
339
|
+
return Object.fromEntries(Object.entries(txt).map(([key, value]) => [key, Buffer.isBuffer(value) ? value.toString('utf8') : String(value)]));
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
exports.mDNS = mDNS;
|
|
344
|
+
//# sourceMappingURL=plugin.cjs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.cjs.js","sources":["../build/electron/mdns.js"],"sourcesContent":["import Bonjour from 'bonjour-service';\nimport { ipcMain } from 'electron';\n/**\n * Electron main-process implementation of the mDNS/Bonjour functionality.\n *\n * Uses the `bonjour-service` package to:\n * - publish (advertise) a single service;\n * - discover services of a given type and normalize results to the shared schema;\n * - wire the API over Electron's ipcMain (see registerIpc/attachOnReady).\n *\n * Notes:\n * - Instance name matching is normalized and prefix-safe, mirroring iOS/Android behavior.\n * - TXT records are forwarded as strings when present.\n */\nexport class mDNS {\n constructor() {\n this.publishTimeoutMs = 5000;\n this.stopTimeoutMs = 3000;\n this.broadcastQueue = Promise.resolve();\n this.destroyed = false;\n //<editor-fold desc=\"Init/Destroy\">\n this.ipcRegistered = false;\n //</editor-fold>\n this.bonjour = new Bonjour();\n }\n registerIpc() {\n if (this.ipcRegistered)\n return;\n try {\n ipcMain.removeHandler('mdns:startBroadcast');\n ipcMain.removeHandler('mdns:stopBroadcast');\n ipcMain.removeHandler('mdns:discover');\n ipcMain.removeHandler('mdns:getPluginPlatform');\n }\n catch (_a) {\n /* ignore */\n }\n ipcMain.handle('mdns:startBroadcast', (_evt, o) => this.startBroadcast(o));\n ipcMain.handle('mdns:stopBroadcast', () => this.stopBroadcast());\n ipcMain.handle('mdns:discover', (_evt, o) => this.discover(o));\n ipcMain.handle('mdns:getPluginPlatform', () => this.getPluginPlatform());\n this.ipcRegistered = true;\n }\n unregisterIpc() {\n if (!this.ipcRegistered)\n return;\n try {\n ipcMain.removeHandler('mdns:startBroadcast');\n ipcMain.removeHandler('mdns:stopBroadcast');\n ipcMain.removeHandler('mdns:discover');\n ipcMain.removeHandler('mdns:getPluginPlatform');\n }\n catch (_a) {\n /* ignore */\n }\n this.ipcRegistered = false;\n }\n /** Manual IPC registration (if you set autoRegisterIpc: false). Idempotent. */\n init() {\n this.registerIpc();\n }\n async destroy() {\n this.destroyed = true;\n this.unregisterIpc();\n await this.withBroadcastLock(async () => {\n await this.stopBroadcastUnlocked();\n try {\n this.bonjour.destroy();\n }\n catch (err) {\n console.warn('[mDNS] bonjour.destroy error:', err);\n }\n });\n }\n // ----------------------------- utils -----------------------------\n toErr(err) {\n return err instanceof Error ? err.message : String(err);\n }\n validatePort(port) {\n return Number.isInteger(port) && typeof port === 'number' && port > 0 && port <= 65535\n ? null\n : 'Missing/invalid port';\n }\n isRecord(value) {\n return !!value && typeof value === 'object' && !Array.isArray(value);\n }\n withBroadcastLock(work) {\n // Publish and stop share one Bonjour service; serializing them prevents orphaned advertisers.\n const run = this.broadcastQueue.catch(() => undefined).then(work);\n this.broadcastQueue = run.catch(() => undefined);\n return run;\n }\n normalize(name) {\n return name.replace(/ \\(\\d+\\)$/, '');\n }\n matchesTarget(candidate, target) {\n if (!target)\n return true;\n const c = this.normalize(candidate), t = this.normalize(target);\n return c === t || c.startsWith(t);\n }\n parseType(typeWithDot) {\n const raw = typeof typeWithDot === 'string' && typeWithDot.trim() ? typeWithDot.trim() : '_http._tcp.';\n const s = raw.replace(/\\.$/, '');\n const m = /^_([^.]+)\\._(tcp|udp)$/.exec(s);\n if (!m)\n return { type: 'http', protocol: 'tcp' };\n return { type: m[1], protocol: m[2] };\n }\n toFullType(type, protocol) {\n return `_${type}._${protocol}.`;\n }\n hasCbStop(x) {\n return !!x && typeof x.stop === 'function';\n }\n async safeStopService(svc) {\n if (!svc || !this.hasCbStop(svc))\n return;\n try {\n await new Promise((res) => {\n let settled = false;\n const done = () => {\n if (settled)\n return;\n settled = true;\n if (timeout)\n clearTimeout(timeout);\n res();\n };\n const timeout = setTimeout(done, this.stopTimeoutMs);\n try {\n svc.stop(done);\n }\n catch (e) {\n console.warn('[mDNS] service.stop threw:', e);\n done();\n }\n });\n }\n catch (err) {\n console.warn('[mDNS] service.stop error:', err);\n }\n }\n safeStopBrowser(b) {\n if (!b)\n return;\n try {\n b.stop();\n }\n catch (err) {\n console.warn('[mDNS] browser.stop error:', err);\n }\n }\n // ----------------------------- API -----------------------------\n /**\n * Return the Electron main-process implementation marker.\n */\n async getPluginPlatform() {\n return { platform: 'electron' };\n }\n /**\n * Publish (advertise) a single Bonjour/mDNS service via bonjour-service.\n * @param options See MdnsBroadcastOptions for type/name/port/txt.\n * @returns Result indicating whether publishing is active and the final name.\n */\n async startBroadcast(options) {\n return this.withBroadcastLock(async () => {\n const safeOptions = (options !== null && options !== void 0 ? options : {});\n const portError = this.validatePort(safeOptions.port);\n if (portError)\n return { publishing: false, name: '', error: true, errorMessage: portError };\n if (this.destroyed)\n return { publishing: false, name: '', error: true, errorMessage: 'mDNS instance is destroyed' };\n await this.stopBroadcastUnlocked();\n const { type, protocol } = this.parseType(safeOptions.type);\n return new Promise((resolve) => {\n let settled = false;\n let timeout = null;\n const safeResolve = (r) => {\n if (!settled) {\n settled = true;\n if (timeout) {\n clearTimeout(timeout);\n timeout = null;\n }\n resolve(r);\n }\n };\n try {\n const svc = this.bonjour.publish({\n name: typeof safeOptions.name === 'string' && safeOptions.name.trim()\n ? safeOptions.name.trim()\n : 'DevIOArtsMDNS',\n type,\n protocol,\n port: safeOptions.port,\n txt: this.isRecord(safeOptions.txt) ? this.normalizeTxt(safeOptions.txt) : undefined,\n });\n const cleanupListeners = () => {\n try {\n svc.removeListener('up', onUp);\n svc.removeListener('error', onError);\n }\n catch (_a) {\n /* ignore */\n }\n };\n const onUp = () => {\n cleanupListeners();\n safeResolve({ publishing: true, name: svc.name || '', error: false, errorMessage: null });\n };\n const onError = (err) => {\n cleanupListeners();\n void this.safeStopService(svc);\n if (this.advertiser === svc)\n this.advertiser = undefined;\n safeResolve({ publishing: false, name: '', error: true, errorMessage: this.toErr(err) });\n };\n const onTimeout = () => {\n cleanupListeners();\n void this.safeStopService(svc);\n if (this.advertiser === svc)\n this.advertiser = undefined;\n safeResolve({\n publishing: false,\n name: '',\n error: true,\n errorMessage: `Timed out waiting for service publish after ${this.publishTimeoutMs}ms`,\n });\n };\n svc.once('up', onUp);\n svc.once('error', onError);\n timeout = setTimeout(onTimeout, this.publishTimeoutMs);\n this.advertiser = svc;\n }\n catch (e) {\n safeResolve({ publishing: false, name: '', error: true, errorMessage: this.toErr(e) });\n }\n });\n });\n }\n /**\n * Stop advertising the current service if any and clear internal state.\n * @returns Result indicating whether the advertiser is active and error info.\n */\n async stopBroadcast() {\n return this.withBroadcastLock(() => this.stopBroadcastUnlocked());\n }\n async stopBroadcastUnlocked() {\n try {\n if (this.advertiser) {\n await this.safeStopService(this.advertiser);\n this.advertiser = undefined;\n }\n return { publishing: false, error: false, errorMessage: null };\n }\n catch (e) {\n return { publishing: false, error: true, errorMessage: this.toErr(e) };\n }\n }\n /**\n * Discover services of the given type and optionally filter by instance name.\n * Deduplicates by (name:port), collects IPv4/IPv6 addresses and TXT, and\n * resolves with either an early-exit match or after a timeout.\n * @param options See MdnsDiscoverOptions for type/name/timeout.\n */\n async discover(options = {}) {\n const safeOptions = (options !== null && options !== void 0 ? options : {});\n if (this.destroyed) {\n return { error: true, errorMessage: 'mDNS instance is destroyed', servicesFound: 0, services: [] };\n }\n const { type, protocol } = this.parseType(safeOptions.type);\n const targetId = typeof safeOptions.name === 'string' && safeOptions.name ? safeOptions.name : null;\n const timeoutMs = typeof safeOptions.timeout === 'number' ? safeOptions.timeout : 3000;\n let browser = null;\n const services = [];\n let hadError = false;\n let errMsg = null;\n return new Promise((resolve) => {\n let timer = null;\n let settled = false;\n const finish = () => {\n if (settled)\n return;\n settled = true;\n if (browser) {\n this.safeStopBrowser(browser);\n browser = null;\n }\n if (timer) {\n clearTimeout(timer);\n timer = null;\n }\n resolve({\n error: hadError,\n errorMessage: errMsg,\n services,\n servicesFound: services.length,\n });\n };\n try {\n browser = this.bonjour.find({ type, protocol }, (s) => {\n var _a;\n if (!this.matchesTarget(s.name || '', targetId))\n return;\n const item = {\n name: s.name || '',\n type: this.toFullType(type, protocol),\n domain: 'local.',\n port: (_a = s.port) !== null && _a !== void 0 ? _a : 0,\n hosts: Array.isArray(s.addresses) ? s.addresses.slice() : [],\n txt: s.txt && Object.keys(s.txt).length ? this.normalizeTxt(s.txt) : undefined,\n };\n const key = `${item.name}:${item.port}`;\n if (!services.some((x) => `${x.name}:${x.port}` === key))\n services.push(item);\n if (targetId && this.matchesTarget(item.name, targetId))\n finish();\n });\n // Record error and let the timeout conclude; results will still be returned.\n const onBrowserError = (err) => {\n hadError = true;\n errMsg = this.toErr(err);\n };\n browser.on('error', onBrowserError);\n timer = setTimeout(finish, Math.max(0, timeoutMs));\n }\n catch (err) {\n hadError = true;\n errMsg = this.toErr(err);\n finish();\n }\n });\n }\n normalizeTxt(txt) {\n return Object.fromEntries(Object.entries(txt).map(([key, value]) => [key, Buffer.isBuffer(value) ? value.toString('utf8') : String(value)]));\n }\n}\n//# sourceMappingURL=mdns.js.map"],"names":["ipcMain"],"mappings":"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"}
|
package/electron/global.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ import type {
|
|
|
4
4
|
MdnsBroadcastResult,
|
|
5
5
|
MdnsDiscoverOptions,
|
|
6
6
|
MdnsDiscoverResult,
|
|
7
|
+
MdnsPluginPlatformResult,
|
|
7
8
|
MdnsStopResult,
|
|
8
9
|
} from '../src/definitions'; // Types only; no runtime import
|
|
9
10
|
|
|
@@ -14,6 +15,7 @@ declare global {
|
|
|
14
15
|
* Primary name with the same casing as iOS jsName.
|
|
15
16
|
*/
|
|
16
17
|
mDNS: {
|
|
18
|
+
getPluginPlatform(): Promise<MdnsPluginPlatformResult>;
|
|
17
19
|
startBroadcast(options: MdnsBroadcastOptions): Promise<MdnsBroadcastResult>;
|
|
18
20
|
stopBroadcast(): Promise<MdnsStopResult>;
|
|
19
21
|
discover(options?: MdnsDiscoverOptions): Promise<MdnsDiscoverResult>;
|
package/electron/mdns-bridge.cjs
CHANGED
|
@@ -3,9 +3,14 @@
|
|
|
3
3
|
// const { createMDNSAPI } = require('.../electron/mdns-bridge.cjs')
|
|
4
4
|
// contextBridge.exposeInMainWorld('mDNS', createMDNSAPI({ ipcRenderer }))
|
|
5
5
|
// contextBridge.exposeInMainWorld('mdns', createMDNSAPI({ ipcRenderer })) // alias
|
|
6
|
-
// eslint-disable-next-line no-undef
|
|
7
6
|
module.exports.createMDNSAPI = ({ ipcRenderer }) => {
|
|
8
7
|
return {
|
|
8
|
+
/**
|
|
9
|
+
* Return the platform implementation that handled this call.
|
|
10
|
+
* @returns {Promise<{platform: 'electron'}>}
|
|
11
|
+
*/
|
|
12
|
+
getPluginPlatform: () => ipcRenderer.invoke('mdns:getPluginPlatform'),
|
|
13
|
+
|
|
9
14
|
/**
|
|
10
15
|
* Start advertising a Bonjour/mDNS service.
|
|
11
16
|
* @param {{type?: string, name: string, port: number, txt?: Record<string,string>}} options
|
|
@@ -21,9 +26,9 @@ module.exports.createMDNSAPI = ({ ipcRenderer }) => {
|
|
|
21
26
|
|
|
22
27
|
/**
|
|
23
28
|
* Discover services of a given type, optional normalized exact/prefix name filter.
|
|
24
|
-
* @param {{type?: string,
|
|
25
|
-
* @returns {Promise<{services: Array<{name:string,type:string,domain:string,port:number,hosts
|
|
29
|
+
* @param {{type?: string, name?: string, timeout?: number}} [options]
|
|
30
|
+
* @returns {Promise<{error:boolean,errorMessage:string|null,servicesFound:number,services: Array<{name:string,type:string,domain:string,port:number,hosts:string[],txt?:Record<string,string>}>}>}
|
|
26
31
|
*/
|
|
27
32
|
discover: (options) => ipcRenderer.invoke('mdns:discover', options),
|
|
28
33
|
}
|
|
29
|
-
}
|
|
34
|
+
}
|