@devioarts/capacitor-mdns 0.1.0 → 0.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.
Files changed (43) hide show
  1. package/CHANGELOG.md +110 -0
  2. package/DevioartsCapacitorMdns.podspec +3 -3
  3. package/Package.swift +1 -1
  4. package/README.md +221 -37
  5. package/android/build.gradle +3 -9
  6. package/android/src/main/java/com/devioarts/capacitor/mdns/AndroidNsdBackend.kt +145 -0
  7. package/android/src/main/java/com/devioarts/capacitor/mdns/MdnsOptions.kt +32 -0
  8. package/android/src/main/java/com/devioarts/capacitor/mdns/MdnsValidation.kt +26 -0
  9. package/android/src/main/java/com/devioarts/capacitor/mdns/NsdBackend.kt +59 -0
  10. package/android/src/main/java/com/devioarts/capacitor/mdns/mDNS.kt +467 -243
  11. package/android/src/main/java/com/devioarts/capacitor/mdns/mDNSPlugin.kt +80 -57
  12. package/dist/docs.json +250 -14
  13. package/dist/esm/definitions.d.ts +64 -17
  14. package/dist/esm/definitions.js.map +1 -1
  15. package/dist/esm/index.js +22 -2
  16. package/dist/esm/index.js.map +1 -1
  17. package/dist/esm/web.d.ts +6 -1
  18. package/dist/esm/web.js +23 -0
  19. package/dist/esm/web.js.map +1 -1
  20. package/dist/plugin.cjs.js +45 -2
  21. package/dist/plugin.cjs.js.map +1 -1
  22. package/dist/plugin.js +45 -2
  23. package/dist/plugin.js.map +1 -1
  24. package/docs/electron.md +29 -3
  25. package/docs/platform-setup.md +6 -0
  26. package/docs/playground.md +33 -2
  27. package/docs/runtime-behavior.md +68 -2
  28. package/electron/dist/plugin-settings.js +10 -3
  29. package/electron/dist/plugin-settings.js.map +1 -1
  30. package/electron/dist/plugin.cjs.js +519 -89
  31. package/electron/dist/plugin.cjs.js.map +1 -1
  32. package/electron/mdns-bridge.cjs +25 -2
  33. package/electron/mdns.ts +514 -81
  34. package/electron/rollup.config.mjs +1 -1
  35. package/electron/src/index.ts +1 -0
  36. package/electron/src/plugin-settings.ts +10 -3
  37. package/electron/types-public/index.d.ts +25 -3
  38. package/ios/Sources/mDNSPlugin/mDNS.swift +407 -117
  39. package/ios/Sources/mDNSPlugin/mDNSPlugin.swift +77 -24
  40. package/ios/Tests/mDNSPluginTests/BridgeTests.swift +46 -0
  41. package/ios/Tests/mDNSPluginTests/MDNSTests.swift +490 -0
  42. package/package.json +11 -4
  43. package/ios/Tests/mDNSPluginTests/mDNSPluginTests.swift +0 -9
package/CHANGELOG.md ADDED
@@ -0,0 +1,110 @@
1
+ # Changelog
2
+
3
+ ## [0.2.0] - 2026-11-07
4
+
5
+ ### Upgrade from 0.1.0
6
+
7
+ - Existing method signatures and result shapes are retained. Continuous discovery is additive,
8
+ but validation, failure reporting and overlapping discovery behavior have changed as noted below.
9
+ - iOS now declares a minimum deployment target of 15.0. Capacitor dependencies are restricted to
10
+ version 8; applications using another major version are not supported.
11
+ - Service types, instance names, TXT records and timeouts are validated more strictly. Previously
12
+ tolerated invalid inputs can now return `error: true`.
13
+ - A valid new `discover()` cancels the previous request with an error. On iOS, discovery without
14
+ a name filter now waits for the complete timeout. Check `error` before consuming results;
15
+ errors discard partial results, and a failed stop can return `publishing: true`.
16
+ - Electron applications must install `bonjour-service@~1.4.0` and rerun `npx cap-electron sync`.
17
+ Manual IPC integrations using a custom renderer origin must configure `trustedOrigins`.
18
+
19
+ ### Added
20
+
21
+ - Continuous multi-type discovery on iOS, Android and Electron through `watchServices()` and
22
+ `stopWatching()`, with `serviceFound`, `serviceLost` and `watchError` listeners. Valid replacement
23
+ calls stop previous watchers; stopping leaves advertisements and one-shot discovery independent.
24
+ Thanks to [Idrimi](https://github.com/Idrimi) for the original feature in
25
+ [PR #7](https://github.com/devioarts/capacitor-mdns/pull/7).
26
+ - Full found/lost snapshots, duplicate-type normalization, stale-callback guards, native resolve
27
+ retries, shared Android resolver scheduling and multicast locks, and Electron TTL expiry / IPC events.
28
+ - Resolved Android NSD TXT attributes, optional service hostnames, playground live service lists / errors / TXT publication and
29
+ regression tests for watcher lifecycle and both Electron integration routes.
30
+
31
+ ### Fixed
32
+
33
+ - CocoaPods source tags now use the repository's `v` prefix. npm archives include this changelog.
34
+ - Electron: a failed response to an incoming Bonjour query no longer permanently blocks later
35
+ publication, discovery or watches. Fatal transport errors still stop affected operations.
36
+ - Electron: name conflicts fail when the probe detects them, and stopping an unpublished service
37
+ no longer sends goodbye records for another publisher's name. Missing generated registration
38
+ reports the required `npx cap-electron sync` step.
39
+ - Electron: goodbye is preserved if an announcement has started but its send callback is still pending;
40
+ stopped services cannot reannounce after a late callback. Duplicate discovered addresses are removed.
41
+ - The supported `bonjour-service` range is limited to `~1.4.0` pending verification of probe cleanup
42
+ behavior in later minor versions; package, playground and installation instructions use the same range.
43
+ - Discovered addresses prefer IPv4 on all platforms while preserving native IPv6 scope suffixes.
44
+ Added regressions for packet failures, Bonjour teardown, address ordering, native bridge input
45
+ validation and Android recovery after a late unregistration confirmation.
46
+
47
+ - Android: NSD callbacks (delivered on NsdManager's internal thread) are now marshalled to the main thread before touching any state, removing data races between discovery results, the timeout, and publish completion. A publish confirmation racing the publish timeout can no longer complete the call twice.
48
+ - Android: before API 34 only one `resolveService` may be active, so concurrent resolves were silently dropped and services lost. Resolves are now queued, retried on `FAILURE_ALREADY_ACTIVE`, and individually timed out.
49
+ - Android: stopping, replacing or timing out a pending registration cancels it immediately through its listener, allowing subsequent publication. Late callbacks cannot resurrect a cancelled service. `close()` fails pending discovery.
50
+ - iOS: discovery waits for the entire requested timeout unless a named target resolves with an IP address, retaining late peers even after a failed or filtered resolve.
51
+ - iOS: the `NWBrowser` duplicate check used un-normalized type/domain, so every browse update spawned new resolvers for already known services.
52
+ - iOS: a denied Local Network permission is now reported as an error instead of an empty discovery result.
53
+ - All platforms validate service types, UTF-8 instance/TXT lengths and string-only TXT before stopping an active advertisement. Android now publishes TXT as well.
54
+
55
+ - Electron: a malformed service type (e.g. `http`, `_http._xyz.`) is now rejected with an error instead of being silently advertised/browsed as `_http._tcp.`, matching iOS and Android. An invalid type no longer stops a broadcast that is already running.
56
+ - All platforms reject invalid timeouts, clamp valid delays and use the same default broadcast name. A new valid `discover()` replaces its predecessor; errors return empty results. Dots and hyphens compare equally in name filters.
57
+ - Electron: transport errors fail pending publication, name conflicts are reported explicitly, and discovery handles late address records. Destroy ends pending discoveries and late callbacks cannot mutate completed results.
58
+ - Electron: manual IPC checks trusted top-level senders and event recipients.
59
+ - npm archives exclude local audit files while retaining SwiftPM tests. Android declares coroutines directly and lint failures block builds. iOS requires version 15, matching Capacitor 8.
60
+
61
+ ### Changed
62
+
63
+ - `bonjour-service` is declared as an optional peer dependency (needed by Electron apps only).
64
+ - Electron: `new mDNS(bonjour?, options?)` accepts an injectable Bonjour implementation and timeouts for tests.
65
+ - Android: NSD access moved behind an internal `NsdBackend` seam (`AndroidNsdBackend` in production) so the logic is unit-testable on the JVM.
66
+ - iOS: `MDNS` exposes internal factories and timers for tests.
67
+ - Removed the unused disabled Dependabot template and Android instrumentation placeholder. Playground lint uses the installed flat React configuration and ignores generated native projects.
68
+
69
+ ### Tests
70
+
71
+ - Added deterministic Electron regressions for validation, publication/stop failures, replacement, late addresses, TTL expiry, IPC trust and bridge subscriptions, plus real network discovery tests.
72
+ - Added JVM and iOS simulator regressions for callbacks, timeouts, replacement, UTF-8 validation, resolver scheduling, watcher cleanup and stale events. Removed template placeholder tests.
73
+
74
+ ## [0.1.0]
75
+
76
+ Compared with `v0.0.3`.
77
+
78
+ ### Added
79
+
80
+ - Added `getPluginPlatform()` to the public API, returning `ios`, `android`, `electron`, or `web` from the implementation that handled the call.
81
+ - Added Capacitor Electron package exports, public Electron type declarations, plugin metadata for `devioarts/capacitor-electron`, and a dedicated Electron build step.
82
+ - Added Electron IPC support for `getPluginPlatform()` and kept the manual preload bridge available through `electron/mdns-bridge.cjs`.
83
+ - Added an in-repository playground app that exercises broadcast, discovery, Electron bridge usage, logging, and runtime platform detection.
84
+ - Added focused docs for platform setup, Electron setup, playground usage, and runtime behavior.
85
+ - Added Electron end-to-end tests for publish/discover/stop behavior, platform detection, invalid input handling, and overlapping broadcast calls.
86
+ - Added GitHub issue templates, pull request template, CI workflow, a disabled Dependabot template, and funding metadata.
87
+
88
+ ### Changed
89
+
90
+ - `startBroadcast()` on iOS, Android, and Electron is now guarded by a publish timeout so native/runtime callbacks cannot leave the JavaScript promise pending forever.
91
+ - Starting a new advertisement now stops or replaces the previous active advertisement; the plugin keeps only one active broadcast at a time.
92
+ - Discovery sessions are now timeboxed and clean up native listeners, browsers, service-info callbacks, and resolvers more reliably.
93
+ - Overlapping discovery calls are serialized or safely isolated from stale callbacks, depending on platform behavior.
94
+ - Service type and name inputs are trimmed and normalized consistently across supported platforms.
95
+ - Port validation now requires values in the `1..65535` range.
96
+ - Android now declares `INTERNET` and `CHANGE_WIFI_MULTICAST_STATE` permissions in the plugin manifest for merge during `npx cap sync`.
97
+ - Package exports now expose the root plugin, Electron runtime entry points, Electron settings, the manual bridge, and `package.json`.
98
+ - Build, clean, lint, and test scripts now include the Electron runtime and e2e test pipeline.
99
+ - README setup and API documentation were regenerated and reorganized around the maintained in-repo playground and docs.
100
+
101
+ ### Fixed
102
+
103
+ - Fixed web fallback behavior so unsupported browser calls return shaped errors instead of success-like results.
104
+ - Fixed pending publish promises when iOS or Android publishing is stopped, replaced, fails, or times out.
105
+ - Fixed Android discovery cleanup and listener handling to avoid old callbacks completing a newer request.
106
+ - Fixed Android discovery failure reporting so start failures surface through the documented error shape.
107
+ - Fixed iOS discovery session handling so stale NWBrowser, NetServiceBrowser, or resolver callbacks cannot complete a newer request.
108
+ - Fixed iOS discovery failures to return an error result instead of silently completing as a clean empty search.
109
+ - Fixed TXT record normalization on iOS and Electron so discovered values are returned as strings.
110
+ - Fixed Electron broadcast stop/destroy handling to avoid orphaned Bonjour advertisers.
@@ -9,9 +9,9 @@ Pod::Spec.new do |s|
9
9
  s.license = package['license']
10
10
  s.homepage = package['repository']['url']
11
11
  s.author = package['author']
12
- s.source = { :git => package['repository']['url'], :tag => s.version.to_s }
12
+ s.source = { :git => package['repository']['url'], :tag => "v#{s.version}" }
13
13
  s.source_files = 'ios/Sources/**/*.{swift,h,m,c,cc,mm,cpp}'
14
- s.ios.deployment_target = '14.0'
15
- s.dependency 'Capacitor'
14
+ s.ios.deployment_target = '15.0'
15
+ s.dependency 'Capacitor', '~> 8.0'
16
16
  s.swift_version = '5.1'
17
17
  end
package/Package.swift CHANGED
@@ -3,7 +3,7 @@ import PackageDescription
3
3
 
4
4
  let package = Package(
5
5
  name: "DevioartsCapacitorMdns",
6
- platforms: [.iOS(.v14)],
6
+ platforms: [.iOS(.v15)],
7
7
  products: [
8
8
  .library(
9
9
  name: "DevioartsCapacitorMdns",
package/README.md CHANGED
@@ -3,6 +3,8 @@
3
3
  mDNS plugin for Capacitor that supports Bonjour/mDNS advertisements and discovery on iOS,
4
4
  Android, Electron, and a safe web fallback.
5
5
 
6
+ **Supported Capacitor version: v8. iOS 15 or later is required.**
7
+
6
8
  #### Supported platforms: ✓ iOS ✓ Android ✓ Electron ✓ Web fallback
7
9
 
8
10
  The in-repository [`playground`](./playground) is the example app used during development.
@@ -14,6 +16,16 @@ npm install @devioarts/capacitor-mdns
14
16
  npx cap sync
15
17
  ```
16
18
 
19
+ For Electron, also install `bonjour-service@~1.4.0` and run `npx cap-electron sync`.
20
+ See the [Electron setup](./docs/electron.md) for details.
21
+
22
+ ## Upgrading from 0.1.0
23
+
24
+ Version 0.2.0 retains the existing method signatures and result shapes and adds continuous
25
+ discovery. It also tightens input validation, changes overlapping discovery and error handling,
26
+ and raises the declared iOS minimum to 15.0. Review the
27
+ [upgrade notes](./CHANGELOG.md#020---2026-11-07) before updating an existing application.
28
+
17
29
  ## Usage
18
30
 
19
31
  ```ts
@@ -26,8 +38,41 @@ const result = await mDNS.discover({ type: '_http._tcp.', timeout: 3000 });
26
38
  await mDNS.stopBroadcast();
27
39
  ```
28
40
 
41
+ ## Continuous discovery
42
+
43
+ Thank you, [Idrimi](https://github.com/Idrimi), for contributing the original continuous discovery
44
+ feature in [PR #7](https://github.com/devioarts/capacitor-mdns/pull/7).
45
+
46
+ `watchServices()` monitors multiple service types on iOS, Android and Electron until stopped.
47
+ Register listeners before starting; a new valid call replaces the previous watch.
48
+
49
+ ```ts
50
+ const found = await mDNS.addListener('serviceFound', ({ service }) => {
51
+ console.log('Found', service.name, service.hosts, service.port);
52
+ });
53
+ const lost = await mDNS.addListener('serviceLost', ({ service }) => {
54
+ console.log('Lost', service.name, service.hosts, service.port);
55
+ });
56
+ const errors = await mDNS.addListener('watchError', (event) => {
57
+ console.error(event.type, event.errorMessage, event.watching);
58
+ });
59
+
60
+ const result = await mDNS.watchServices({
61
+ types: ['_http._tcp.', '_airplay._tcp.', '_googlecast._tcp.'],
62
+ });
63
+ // Later, including when leaving the screen:
64
+ await mDNS.stopWatching();
65
+ await Promise.all([found.remove(), lost.remove(), errors.remove()]);
66
+ ```
67
+
68
+ Found/lost events contain the full service snapshot; `hosts` is always an array. A service
69
+ that disappears before resolving emits neither event. Browser errors stop watching and emit
70
+ `watchError` with `watching: false`; exhausted resolution retries emit it with `watching: true`.
71
+ `stopWatching()` leaves broadcasting and one-shot discovery running. Browsers do not support mDNS.
72
+
29
73
  ## Platform Setup
30
74
 
75
+
31
76
  Android requires mDNS/network permissions in `AndroidManifest.xml`; the plugin also declares them
32
77
  so they are merged during sync. iOS requires local network keys in `Info.plist`.
33
78
  Electron support is intended for [`devioarts/capacitor-electron`](https://github.com/devioarts/capacitor-electron)
@@ -48,6 +93,11 @@ Detailed setup lives in:
48
93
  * [`startBroadcast(...)`](#startbroadcast)
49
94
  * [`stopBroadcast()`](#stopbroadcast)
50
95
  * [`discover(...)`](#discover)
96
+ * [`watchServices(...)`](#watchservices)
97
+ * [`stopWatching()`](#stopwatching)
98
+ * [`addListener('serviceFound' | 'serviceLost', ...)`](#addlistenerservicefound--servicelost-)
99
+ * [`addListener('watchError', ...)`](#addlistenerwatcherror-)
100
+ * [`removeAllListeners()`](#removealllisteners)
51
101
  * [Interfaces](#interfaces)
52
102
  * [Type Aliases](#type-aliases)
53
103
 
@@ -118,6 +168,81 @@ Discover services of a given type and optionally filter by instance name.
118
168
  --------------------
119
169
 
120
170
 
171
+ ### watchServices(...)
172
+
173
+ ```typescript
174
+ watchServices(options: MdnsWatchOptions) => Promise<MdnsWatchResult>
175
+ ```
176
+
177
+ Continuously watch several service types. A valid call replaces the previous watch.
178
+ Register listeners before starting. Each resolved service emits `serviceFound` once;
179
+ disappearance emits `serviceLost` with its last snapshot. No loss is emitted for an
180
+ unresolved service. Watching and one-shot discovery can run together.
181
+ Thanks to Idrimi for contributing the original continuous discovery feature (PR #7).
182
+
183
+ | Param | Type |
184
+ | ------------- | ------------------------------------------------------------- |
185
+ | **`options`** | <code><a href="#mdnswatchoptions">MdnsWatchOptions</a></code> |
186
+
187
+ **Returns:** <code>Promise&lt;<a href="#mdnswatchresult">MdnsWatchResult</a>&gt;</code>
188
+
189
+ --------------------
190
+
191
+
192
+ ### stopWatching()
193
+
194
+ ```typescript
195
+ stopWatching() => Promise<MdnsWatchStopResult>
196
+ ```
197
+
198
+ Stop all watchers. No events from that watch are emitted after this resolves.
199
+
200
+ **Returns:** <code>Promise&lt;<a href="#mdnswatchstopresult">MdnsWatchStopResult</a>&gt;</code>
201
+
202
+ --------------------
203
+
204
+
205
+ ### addListener('serviceFound' | 'serviceLost', ...)
206
+
207
+ ```typescript
208
+ addListener(eventName: 'serviceFound' | 'serviceLost', handler: (event: MdnsServiceEvent) => void) => Promise<PluginListenerHandle>
209
+ ```
210
+
211
+ | Param | Type |
212
+ | --------------- | --------------------------------------------------------------------------------- |
213
+ | **`eventName`** | <code>'serviceFound' \| 'serviceLost'</code> |
214
+ | **`handler`** | <code>(event: <a href="#mdnsserviceevent">MdnsServiceEvent</a>) =&gt; void</code> |
215
+
216
+ **Returns:** <code>Promise&lt;<a href="#pluginlistenerhandle">PluginListenerHandle</a>&gt;</code>
217
+
218
+ --------------------
219
+
220
+
221
+ ### addListener('watchError', ...)
222
+
223
+ ```typescript
224
+ addListener(eventName: 'watchError', handler: (event: MdnsWatchErrorEvent) => void) => Promise<PluginListenerHandle>
225
+ ```
226
+
227
+ | Param | Type |
228
+ | --------------- | --------------------------------------------------------------------------------------- |
229
+ | **`eventName`** | <code>'watchError'</code> |
230
+ | **`handler`** | <code>(event: <a href="#mdnswatcherrorevent">MdnsWatchErrorEvent</a>) =&gt; void</code> |
231
+
232
+ **Returns:** <code>Promise&lt;<a href="#pluginlistenerhandle">PluginListenerHandle</a>&gt;</code>
233
+
234
+ --------------------
235
+
236
+
237
+ ### removeAllListeners()
238
+
239
+ ```typescript
240
+ removeAllListeners() => Promise<void>
241
+ ```
242
+
243
+ --------------------
244
+
245
+
121
246
  ### Interfaces
122
247
 
123
248
 
@@ -137,24 +262,24 @@ Result of startBroadcast(). Indicates whether advertising is active
137
262
  and the final service name. On failure, `error` is true and `errorMessage`
138
263
  describes the issue.
139
264
 
140
- | Prop | Type | Description |
141
- | ------------------ | --------------------------- | -------------------------------------------------------------------- |
142
- | **`error`** | <code>boolean</code> | True if the operation failed. |
143
- | **`errorMessage`** | <code>string \| null</code> | Error description or null on success. |
144
- | **`name`** | <code>string</code> | Final (possibly uniquified) service instance name. Empty on failure. |
145
- | **`publishing`** | <code>boolean</code> | Whether the advertiser is currently active. |
265
+ | Prop | Type | Description |
266
+ | ------------------ | --------------------------- | ----------------------------------------------------------------------------- |
267
+ | **`error`** | <code>boolean</code> | True if the operation failed. |
268
+ | **`errorMessage`** | <code>string \| null</code> | Error description or null on success. |
269
+ | **`name`** | <code>string</code> | Final (possibly uniquified) service instance name. Empty on failure. |
270
+ | **`publishing`** | <code>boolean</code> | Whether an advertiser is active, or may still be active after failed cleanup. |
146
271
 
147
272
 
148
273
  #### MdnsBroadcastOptions
149
274
 
150
275
  Options for starting a Bonjour/mDNS advertisement.
151
276
 
152
- | Prop | Type | Description |
153
- | ---------- | ------------------------------------------- | --------------------------------------------- |
154
- | **`type`** | <code>string</code> | Service type (including the trailing dot). |
155
- | **`name`** | <code>string</code> | Service instance name. |
156
- | **`port`** | <code>number</code> | TCP port to advertise. |
157
- | **`txt`** | <code><a href="#mdnstxt">MdnsTxt</a></code> | Optional TXT key–value pairs (UTF-8 strings). |
277
+ | Prop | Type | Description |
278
+ | ---------- | ------------------------------------------- | ---------------------------------------------------------------------------- |
279
+ | **`type`** | <code>string</code> | Service type (including the trailing dot). |
280
+ | **`name`** | <code>string</code> | Service instance name (maximum 63 UTF-8 bytes). Defaults to `DevIOArtsMDNS`. |
281
+ | **`port`** | <code>number</code> | TCP port to advertise. |
282
+ | **`txt`** | <code><a href="#mdnstxt">MdnsTxt</a></code> | Optional TXT key–value pairs (UTF-8 strings). |
158
283
 
159
284
 
160
285
  #### MdnsStopResult
@@ -162,23 +287,23 @@ Options for starting a Bonjour/mDNS advertisement.
162
287
  Result of stopBroadcast(). Indicates whether the advertiser is active
163
288
  after the call (normally false) and includes error information.
164
289
 
165
- | Prop | Type | Description |
166
- | ------------------ | --------------------------- | ------------------------------------------------------------------- |
167
- | **`error`** | <code>boolean</code> | True if an error occurred while stopping. |
168
- | **`errorMessage`** | <code>string \| null</code> | Error description or null on success. |
169
- | **`publishing`** | <code>boolean</code> | Whether the advertiser remains active (should be false on success). |
290
+ | Prop | Type | Description |
291
+ | ------------------ | --------------------------- | --------------------------------------------------------------------------------------------- |
292
+ | **`error`** | <code>boolean</code> | True if an error occurred while stopping. |
293
+ | **`errorMessage`** | <code>string \| null</code> | Error description or null on success. |
294
+ | **`publishing`** | <code>boolean</code> | False after confirmed stop; true when stopping failed and the advertiser may still be active. |
170
295
 
171
296
 
172
297
  #### MdnsDiscoverResult
173
298
 
174
299
  Result of discover(). Contains normalized services and error information.
175
300
 
176
- | Prop | Type | Description |
177
- | ------------------- | --------------------------- | ------------------------------------------------------------------------------ |
178
- | **`error`** | <code>boolean</code> | True if discovery encountered an error (partial results may still be present). |
179
- | **`errorMessage`** | <code>string \| null</code> | Error description or null when no error occurred. |
180
- | **`servicesFound`** | <code>number</code> | Convenience count equal to services.length. |
181
- | **`services`** | <code>MdnsService[]</code> | Normalized list of discovered services. |
301
+ | Prop | Type | Description |
302
+ | ------------------- | --------------------------- | ---------------------------------------------------------------------------------------- |
303
+ | **`error`** | <code>boolean</code> | True if discovery encountered an error (partial results may still be present). |
304
+ | **`errorMessage`** | <code>string \| null</code> | Error description or null when no error occurred. |
305
+ | **`servicesFound`** | <code>number</code> | Convenience count equal to services.length. |
306
+ | **`services`** | <code>MdnsService[]</code> | Resolved services with numeric addresses. Empty on error; partial results are discarded. |
182
307
 
183
308
 
184
309
  #### MdnsService
@@ -186,26 +311,85 @@ Result of discover(). Contains normalized services and error information.
186
311
  Normalized description of a discovered Bonjour/mDNS service.
187
312
  Returned from {@link mDNSPlugin.discover}.
188
313
 
189
- | Prop | Type | Description |
190
- | ------------ | ------------------------------------------- | ----------------------------------------------------------------------------------------- |
191
- | **`name`** | <code>string</code> | Instance name of the service (may be uniqued by the OS, e.g. "My App (2)"). |
192
- | **`type`** | <code>string</code> | Full service type including the trailing dot, e.g. `"_http._tcp."`. |
193
- | **`domain`** | <code>string</code> | Service domain; typically `"local."`. |
194
- | **`port`** | <code>number</code> | TCP port the service advertises. |
195
- | **`hosts`** | <code>string[]</code> | Resolved numeric IP addresses (IPv4/IPv6). |
196
- | **`txt`** | <code><a href="#mdnstxt">MdnsTxt</a></code> | TXT dictionary (key → value). Usually present on iOS; Android NSD does not populate this. |
314
+ | Prop | Type | Description |
315
+ | -------------- | ------------------------------------------- | ------------------------------------------------------------------------------------- |
316
+ | **`name`** | <code>string</code> | Instance name of the service (may be uniqued by the OS, e.g. "My App (2)"). |
317
+ | **`type`** | <code>string</code> | Full service type including the trailing dot, e.g. `"_http._tcp."`. |
318
+ | **`domain`** | <code>string</code> | Service domain; typically `"local."`. |
319
+ | **`port`** | <code>number</code> | Port the service advertises. |
320
+ | **`hosts`** | <code>string[]</code> | Resolved numeric IP addresses, IPv4 first, then IPv6 with any available scope suffix. |
321
+ | **`hostname`** | <code>string</code> | Host name when supplied by the platform, e.g. `"my-device.local."`. |
322
+ | **`txt`** | <code><a href="#mdnstxt">MdnsTxt</a></code> | TXT dictionary (key → value). |
197
323
 
198
324
 
199
325
  #### MdnsDiscoverOptions
200
326
 
201
327
  Options for Bonjour/mDNS discovery.
202
328
 
203
- | Prop | Type | Description |
204
- | ------------- | -------------------- | ---------------------------------------------------------------- |
205
- | **`type`** | <code>string</code> | Service type (including the trailing dot). |
206
- | **`name`** | <code>string</code> | Optional instance name filter (prefix-safe). |
207
- | **`timeout`** | <code>number</code> | Discovery timeout in milliseconds. |
208
- | **`useNW`** | <code>boolean</code> | iOS-only hint to use `NWBrowser` instead of `NetServiceBrowser`. |
329
+ | Prop | Type | Description |
330
+ | ------------- | -------------------- | ------------------------------------------------------------------------------------------------------------------------- |
331
+ | **`type`** | <code>string</code> | Service type (including the trailing dot). |
332
+ | **`name`** | <code>string</code> | Optional instance name filter (prefix-safe). |
333
+ | **`timeout`** | <code>number</code> | Discovery timeout in milliseconds. Finite numbers only; fractions are truncated and the delay is clamped to 0–2147483647. |
334
+ | **`useNW`** | <code>boolean</code> | iOS-only hint to use `NWBrowser` instead of `NetServiceBrowser`. |
335
+
336
+
337
+ #### MdnsWatchResult
338
+
339
+ Native browsers have been requested; later failures are reported through `watchError`.
340
+
341
+ | Prop | Type |
342
+ | --------------------- | --------------------------- |
343
+ | **`error`** | <code>boolean</code> |
344
+ | **`errorMessage`** | <code>string \| null</code> |
345
+ | **`watchersStarted`** | <code>number</code> |
346
+
347
+
348
+ #### MdnsWatchOptions
349
+
350
+ Options for continuous discovery on iOS, Android and Electron.
351
+
352
+ | Prop | Type | Description |
353
+ | ----------- | --------------------- | ---------------------------------------------------------------------------------- |
354
+ | **`types`** | <code>string[]</code> | Nonempty list of service types. Trailing dots are optional; duplicates are merged. |
355
+
356
+
357
+ #### MdnsWatchStopResult
358
+
359
+ Stops watching independently of any active broadcast.
360
+
361
+ | Prop | Type |
362
+ | ------------------ | --------------------------- |
363
+ | **`error`** | <code>boolean</code> |
364
+ | **`errorMessage`** | <code>string \| null</code> |
365
+ | **`watching`** | <code>boolean</code> |
366
+
367
+
368
+ #### PluginListenerHandle
369
+
370
+ | Prop | Type |
371
+ | ------------ | ----------------------------------------- |
372
+ | **`remove`** | <code>() =&gt; Promise&lt;void&gt;</code> |
373
+
374
+
375
+ #### MdnsServiceEvent
376
+
377
+ Both found and lost events contain a complete service snapshot, including `hosts`.
378
+
379
+ | Prop | Type |
380
+ | ------------- | --------------------------------------------------- |
381
+ | **`service`** | <code><a href="#mdnsservice">MdnsService</a></code> |
382
+
383
+
384
+ #### MdnsWatchErrorEvent
385
+
386
+ Browser failures stop the watch; exhausted service resolution retries leave it running.
387
+
388
+ | Prop | Type |
389
+ | ------------------ | -------------------- |
390
+ | **`type`** | <code>string</code> |
391
+ | **`errorMessage`** | <code>string</code> |
392
+ | **`watching`** | <code>boolean</code> |
209
393
 
210
394
 
211
395
  ### Type Aliases
@@ -1,8 +1,6 @@
1
1
  ext {
2
2
  junitVersion = project.hasProperty('junitVersion') ? rootProject.ext.junitVersion : '4.13.2'
3
3
  androidxAppCompatVersion = project.hasProperty('androidxAppCompatVersion') ? rootProject.ext.androidxAppCompatVersion : '1.7.0'
4
- androidxJunitVersion = project.hasProperty('androidxJunitVersion') ? rootProject.ext.androidxJunitVersion : '1.2.1'
5
- androidxEspressoCoreVersion = project.hasProperty('androidxEspressoCoreVersion') ? rootProject.ext.androidxEspressoCoreVersion : '3.6.1'
6
4
  }
7
5
 
8
6
  buildscript {
@@ -25,9 +23,6 @@ android {
25
23
  defaultConfig {
26
24
  minSdk = project.hasProperty('minSdkVersion') ? rootProject.ext.minSdkVersion : 23
27
25
  targetSdk = project.hasProperty('targetSdkVersion') ? rootProject.ext.targetSdkVersion : 36
28
- versionCode = 1
29
- versionName = "1.0"
30
- testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
31
26
  }
32
27
  buildTypes {
33
28
  release {
@@ -36,7 +31,7 @@ android {
36
31
  }
37
32
  }
38
33
  lint {
39
- abortOnError = false
34
+ abortOnError = true
40
35
  }
41
36
  compileOptions {
42
37
  sourceCompatibility JavaVersion.VERSION_21
@@ -55,10 +50,9 @@ repositories {
55
50
 
56
51
 
57
52
  dependencies {
58
- implementation fileTree(dir: 'libs', include: ['*.jar'])
53
+ implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.8.1"
59
54
  implementation project(':capacitor-android')
60
55
  implementation "androidx.appcompat:appcompat:$androidxAppCompatVersion"
61
56
  testImplementation "junit:junit:$junitVersion"
62
- androidTestImplementation "androidx.test.ext:junit:$androidxJunitVersion"
63
- androidTestImplementation "androidx.test.espresso:espresso-core:$androidxEspressoCoreVersion"
57
+ testImplementation 'org.json:json:20250517'
64
58
  }