@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
@@ -1,3 +1,4 @@
1
+ import type { PluginListenerHandle } from '@capacitor/core';
1
2
  /**
2
3
  * Key–value map for TXT records of a Bonjour/mDNS service.
3
4
  * Values are UTF-8 strings; binary payloads are not supported by this API.
@@ -24,8 +25,10 @@ export interface MdnsPluginPlatformResult {
24
25
  *
25
26
  * @remarks
26
27
  * - `hosts` contains resolved IPv4/IPv6 numeric addresses (no DNS names).
27
- * - iOS returns `txt` when present. Android (NSD) does not expose TXT records via public APIs,
28
- * so `txt` is usually omitted on Android.
28
+ * - IPv4 addresses precede IPv6; order within each family follows discovery order.
29
+ * - Native IPv6 scope suffixes are preserved (`%<scope-id>` on iOS; the OS-provided scope on Android).
30
+ * Electron may return link-local IPv6 without a scope; callers must not assume every address is reachable.
31
+ * - Resolved TXT records are returned when present.
29
32
  * - `domain` is typically `"local."`.
30
33
  *
31
34
  * @public
@@ -37,16 +40,18 @@ export interface MdnsService {
37
40
  type: string;
38
41
  /** Service domain; typically `"local."`. */
39
42
  domain: string;
40
- /** TCP port the service advertises. */
43
+ /** Port the service advertises. */
41
44
  port: number;
42
45
  /**
43
- * Resolved numeric IP addresses (IPv4/IPv6).
46
+ * Resolved numeric IP addresses, IPv4 first, then IPv6 with any available scope suffix.
44
47
  * @example
45
48
  * `["192.168.1.42", "fe80::1234:abcd:..."]`
46
49
  */
47
50
  hosts: string[];
51
+ /** Host name when supplied by the platform, e.g. `"my-device.local."`. */
52
+ hostname?: string;
48
53
  /**
49
- * TXT dictionary (key → value). Usually present on iOS; Android NSD does not populate this.
54
+ * TXT dictionary (key → value).
50
55
  * @remarks Not all services publish TXT data.
51
56
  */
52
57
  txt?: MdnsTxt;
@@ -55,9 +60,10 @@ export interface MdnsService {
55
60
  * Options for starting a Bonjour/mDNS advertisement.
56
61
  *
57
62
  * @remarks
58
- * - The `type` **must** end with a dot (`.`). If omitted, the implementation appends it.
63
+ * - Service types accept an optional trailing dot; results always include it.
59
64
  * - Instance `name` should be short and human-readable; the OS may append `" (n)"` to ensure uniqueness.
60
- * - Android NSD does not expose TXT records to other apps; advertising TXT is supported on iOS.
65
+ * Electron rejects a name conflict instead of renaming the service.
66
+ * - Advertising TXT is supported on iOS, Android and Electron. Invalid input preserves the active advertisement.
61
67
  * - Native implementations guard publish with a timeout and return `error: true` instead of
62
68
  * leaving the Promise pending when the OS does not deliver a publish callback.
63
69
  * - Only one advertisement is active at a time. Starting a new one stops the previous one first.
@@ -72,9 +78,9 @@ export interface MdnsBroadcastOptions {
72
78
  */
73
79
  type?: string;
74
80
  /**
75
- * Service instance name.
81
+ * Service instance name (maximum 63 UTF-8 bytes). Defaults to `DevIOArtsMDNS`.
76
82
  */
77
- name: string;
83
+ name?: string;
78
84
  /**
79
85
  * TCP port to advertise.
80
86
  * @remarks Must be a positive integer (1–65535).
@@ -82,7 +88,7 @@ export interface MdnsBroadcastOptions {
82
88
  port: number;
83
89
  /**
84
90
  * Optional TXT key–value pairs (UTF-8 strings).
85
- * @remarks May be ignored on Android due to platform limitations.
91
+ * @remarks Keys must be unique ignoring case, nonempty printable ASCII without `=`. Each `key=value` entry must fit in 255 UTF-8 bytes. The complete record is limited to 1300 bytes including length prefixes. Non-string values are rejected.
86
92
  */
87
93
  txt?: MdnsTxt;
88
94
  }
@@ -93,8 +99,9 @@ export interface MdnsBroadcastOptions {
93
99
  * - The `name` filter matches the normalized name and also accepts prefix matches
94
100
  * (to handle OS-added `" (n)"` suffixes).
95
101
  * - When `useNW` is `true` on iOS, discovery uses `NWBrowser` for better P2P behavior.
96
- * - Discovery is timeboxed. Concurrent discovery requests are serialized or safely replace
97
- * the previous native session so old callbacks cannot complete a newer request.
102
+ * - A valid new discovery replaces the previous request with an error on every platform.
103
+ * - Dots and hyphens are equivalent when matching names; returned names retain their advertised spelling.
104
+ * - Without a name filter, browsing continues for the entire timeout. With a filter it may finish once a matching IP address resolves.
98
105
  *
99
106
  * @public
100
107
  */
@@ -111,7 +118,7 @@ export interface MdnsDiscoverOptions {
111
118
  */
112
119
  name?: string;
113
120
  /**
114
- * Discovery timeout in milliseconds.
121
+ * Discovery timeout in milliseconds. Finite numbers only; fractions are truncated and the delay is clamped to 0–2147483647.
115
122
  * @defaultValue `3000`
116
123
  */
117
124
  timeout?: number;
@@ -134,7 +141,7 @@ export interface MdnsBroadcastResult {
134
141
  errorMessage: string | null;
135
142
  /** Final (possibly uniquified) service instance name. Empty on failure. */
136
143
  name: string;
137
- /** Whether the advertiser is currently active. */
144
+ /** Whether an advertiser is active, or may still be active after failed cleanup. */
138
145
  publishing: boolean;
139
146
  }
140
147
  /**
@@ -148,7 +155,7 @@ export interface MdnsDiscoverResult {
148
155
  errorMessage: string | null;
149
156
  /** Convenience count equal to services.length. */
150
157
  servicesFound: number;
151
- /** Normalized list of discovered services. */
158
+ /** Resolved services with numeric addresses. Empty on error; partial results are discarded. */
152
159
  services: MdnsService[];
153
160
  }
154
161
  /**
@@ -161,9 +168,36 @@ export interface MdnsStopResult {
161
168
  error: boolean;
162
169
  /** Error description or null on success. */
163
170
  errorMessage: string | null;
164
- /** Whether the advertiser remains active (should be false on success). */
171
+ /** False after confirmed stop; true when stopping failed and the advertiser may still be active. */
165
172
  publishing: boolean;
166
173
  }
174
+ /** Options for continuous discovery on iOS, Android and Electron. */
175
+ export interface MdnsWatchOptions {
176
+ /** Nonempty list of service types. Trailing dots are optional; duplicates are merged. */
177
+ types: string[];
178
+ }
179
+ /** Native browsers have been requested; later failures are reported through `watchError`. */
180
+ export interface MdnsWatchResult {
181
+ error: boolean;
182
+ errorMessage: string | null;
183
+ watchersStarted: number;
184
+ }
185
+ /** Stops watching independently of any active broadcast. */
186
+ export interface MdnsWatchStopResult {
187
+ error: boolean;
188
+ errorMessage: string | null;
189
+ watching: boolean;
190
+ }
191
+ /** Both found and lost events contain a complete service snapshot, including `hosts`. */
192
+ export interface MdnsServiceEvent {
193
+ service: MdnsService;
194
+ }
195
+ /** Browser failures stop the watch; exhausted service resolution retries leave it running. */
196
+ export interface MdnsWatchErrorEvent {
197
+ type: string;
198
+ errorMessage: string;
199
+ watching: boolean;
200
+ }
167
201
  /**
168
202
  * Public API surface of the Capacitor mDNS plugin.
169
203
  *
@@ -210,7 +244,20 @@ export interface mDNSPlugin {
210
244
  *
211
245
  * @param options - {@link MdnsDiscoverOptions}
212
246
  * @returns Promise resolving to `MdnsDiscoverResult`.
213
- * @remarks The result list is normalized across platforms. On Android, `txt` is typically absent.
247
+ * @remarks The result list is normalized across platforms.
214
248
  */
215
249
  discover(options?: MdnsDiscoverOptions): Promise<MdnsDiscoverResult>;
250
+ /**
251
+ * Continuously watch several service types. A valid call replaces the previous watch.
252
+ * Register listeners before starting. Each resolved service emits `serviceFound` once;
253
+ * disappearance emits `serviceLost` with its last snapshot. No loss is emitted for an
254
+ * unresolved service. Watching and one-shot discovery can run together.
255
+ * Thanks to Idrimi for contributing the original continuous discovery feature (PR #7).
256
+ */
257
+ watchServices(options: MdnsWatchOptions): Promise<MdnsWatchResult>;
258
+ /** Stop all watchers. No events from that watch are emitted after this resolves. */
259
+ stopWatching(): Promise<MdnsWatchStopResult>;
260
+ addListener(eventName: 'serviceFound' | 'serviceLost', handler: (event: MdnsServiceEvent) => void): Promise<PluginListenerHandle>;
261
+ addListener(eventName: 'watchError', handler: (event: MdnsWatchErrorEvent) => void): Promise<PluginListenerHandle>;
262
+ removeAllListeners(): Promise<void>;
216
263
  }
@@ -1 +1 @@
1
- {"version":3,"file":"definitions.js","sourceRoot":"","sources":["../../src/definitions.ts"],"names":[],"mappings":"AAAA,qBAAqB","sourcesContent":["// src/definitions.ts\n\n/**\n * Key–value map for TXT records of a Bonjour/mDNS service.\n * Values are UTF-8 strings; binary payloads are not supported by this API.\n * @public\n */\nexport type MdnsTxt = Record<string, string>;\n\n/**\n * Runtime implementation that handled a plugin call.\n * @public\n */\nexport type MdnsPluginPlatform = 'ios' | 'android' | 'electron' | 'web';\n\n/**\n * Result of getPluginPlatform(). Useful for validating that calls are routed\n * through the expected platform bridge.\n * @public\n */\nexport interface MdnsPluginPlatformResult {\n /** Platform implementation that produced this result. */\n platform: MdnsPluginPlatform;\n}\n\n/**\n * Normalized description of a discovered Bonjour/mDNS service.\n * Returned from {@link mDNSPlugin.discover}.\n *\n * @remarks\n * - `hosts` contains resolved IPv4/IPv6 numeric addresses (no DNS names).\n * - iOS returns `txt` when present. Android (NSD) does not expose TXT records via public APIs,\n * so `txt` is usually omitted on Android.\n * - `domain` is typically `\"local.\"`.\n *\n * @public\n */\nexport interface MdnsService {\n /** Instance name of the service (may be uniqued by the OS, e.g. \"My App (2)\"). */\n name: string;\n\n /** Full service type including the trailing dot, e.g. `\"_http._tcp.\"`. */\n type: string;\n\n /** Service domain; typically `\"local.\"`. */\n domain: string;\n\n /** TCP port the service advertises. */\n port: number;\n\n /**\n * Resolved numeric IP addresses (IPv4/IPv6).\n * @example\n * `[\"192.168.1.42\", \"fe80::1234:abcd:...\"]`\n */\n hosts: string[];\n\n /**\n * TXT dictionary (key → value). Usually present on iOS; Android NSD does not populate this.\n * @remarks Not all services publish TXT data.\n */\n txt?: MdnsTxt;\n}\n\n/**\n * Options for starting a Bonjour/mDNS advertisement.\n *\n * @remarks\n * - The `type` **must** end with a dot (`.`). If omitted, the implementation appends it.\n * - Instance `name` should be short and human-readable; the OS may append `\" (n)\"` to ensure uniqueness.\n * - Android NSD does not expose TXT records to other apps; advertising TXT is supported on iOS.\n * - Native implementations guard publish with a timeout and return `error: true` instead of\n * leaving the Promise pending when the OS does not deliver a publish callback.\n * - Only one advertisement is active at a time. Starting a new one stops the previous one first.\n *\n * @public\n */\nexport interface MdnsBroadcastOptions {\n /**\n * Service type (including the trailing dot).\n * @defaultValue `\"_http._tcp.\"`\n * @example `\"_myapp._tcp.\"`\n */\n type?: string;\n\n /**\n * Service instance name.\n */\n name: string;\n\n /**\n * TCP port to advertise.\n * @remarks Must be a positive integer (1–65535).\n */\n port: number;\n\n /**\n * Optional TXT key–value pairs (UTF-8 strings).\n * @remarks May be ignored on Android due to platform limitations.\n */\n txt?: MdnsTxt;\n}\n\n/**\n * Options for Bonjour/mDNS discovery.\n *\n * @remarks\n * - The `name` filter matches the normalized name and also accepts prefix matches\n * (to handle OS-added `\" (n)\"` suffixes).\n * - When `useNW` is `true` on iOS, discovery uses `NWBrowser` for better P2P behavior.\n * - Discovery is timeboxed. Concurrent discovery requests are serialized or safely replace\n * the previous native session so old callbacks cannot complete a newer request.\n *\n * @public\n */\nexport interface MdnsDiscoverOptions {\n /**\n * Service type (including the trailing dot).\n * @defaultValue `\"_http._tcp.\"`\n * @example `\"_comm._tcp.\"`\n */\n type?: string;\n\n /**\n * Optional instance name filter (prefix-safe).\n * @example `\"MyAppName\"`\n */\n name?: string;\n\n /**\n * Discovery timeout in milliseconds.\n * @defaultValue `3000`\n */\n timeout?: number;\n\n /**\n * iOS-only hint to use `NWBrowser` instead of `NetServiceBrowser`.\n * @defaultValue `true`\n */\n useNW?: boolean;\n}\n\n/**\n * Result of startBroadcast(). Indicates whether advertising is active\n * and the final service name. On failure, `error` is true and `errorMessage`\n * describes the issue.\n * @public\n */\nexport interface MdnsBroadcastResult {\n /** True if the operation failed. */\n error: boolean;\n /** Error description or null on success. */\n errorMessage: string | null;\n /** Final (possibly uniquified) service instance name. Empty on failure. */\n name: string;\n /** Whether the advertiser is currently active. */\n publishing: boolean;\n}\n\n/**\n * Result of discover(). Contains normalized services and error information.\n * @public\n */\nexport interface MdnsDiscoverResult {\n /** True if discovery encountered an error (partial results may still be present). */\n error: boolean;\n /** Error description or null when no error occurred. */\n errorMessage: string | null;\n /** Convenience count equal to services.length. */\n servicesFound: number;\n /** Normalized list of discovered services. */\n services: MdnsService[];\n}\n\n/**\n * Result of stopBroadcast(). Indicates whether the advertiser is active\n * after the call (normally false) and includes error information.\n * @public\n */\nexport interface MdnsStopResult {\n /** True if an error occurred while stopping. */\n error: boolean;\n /** Error description or null on success. */\n errorMessage: string | null;\n /** Whether the advertiser remains active (should be false on success). */\n publishing: boolean;\n}\n\n/**\n * Public API surface of the Capacitor mDNS plugin.\n *\n * @example\n * ```ts\n * import { mDNS } from 'capacitor-mdns';\n *\n * // Start advertising\n * await mDNS.startBroadcast({ type: '_http._tcp.', name: 'my.app.id', port: 9235 });\n *\n * // Discover services\n * const { services } = await mDNS.discover({ type: '_http._tcp.', timeout: 3000 });\n *\n * // Stop advertising\n * await mDNS.stopBroadcast();\n * ```\n *\n * @public\n */\nexport interface mDNSPlugin {\n /**\n * Return the platform implementation currently serving plugin calls.\n *\n * @returns Promise resolving to `MdnsPluginPlatformResult`.\n */\n getPluginPlatform(): Promise<MdnsPluginPlatformResult>;\n\n /**\n * Start advertising a Bonjour/mDNS service.\n *\n * @param options - {@link MdnsBroadcastOptions}\n * @returns Promise resolving to `MdnsBroadcastResult` (`true` on success).\n */\n startBroadcast(options: MdnsBroadcastOptions): Promise<MdnsBroadcastResult>;\n\n /**\n * Stop advertising the currently registered service (no-op if none).\n *\n * @returns Promise resolving to `MdnsStopResult`.\n * @remarks The `publishing` flag may be `false` after a successful stop.\n * Stopping is idempotent and is safe to call even if publishing never fully started.\n */\n stopBroadcast(): Promise<MdnsStopResult>;\n\n /**\n * Discover services of a given type and optionally filter by instance name.\n *\n * @param options - {@link MdnsDiscoverOptions}\n * @returns Promise resolving to `MdnsDiscoverResult`.\n * @remarks The result list is normalized across platforms. On Android, `txt` is typically absent.\n */\n discover(options?: MdnsDiscoverOptions): Promise<MdnsDiscoverResult>;\n}\n"]}
1
+ {"version":3,"file":"definitions.js","sourceRoot":"","sources":["../../src/definitions.ts"],"names":[],"mappings":"AAAA,qBAAqB","sourcesContent":["// src/definitions.ts\n\nimport type { PluginListenerHandle } from '@capacitor/core';\n\n/**\n * Key–value map for TXT records of a Bonjour/mDNS service.\n * Values are UTF-8 strings; binary payloads are not supported by this API.\n * @public\n */\nexport type MdnsTxt = Record<string, string>;\n\n/**\n * Runtime implementation that handled a plugin call.\n * @public\n */\nexport type MdnsPluginPlatform = 'ios' | 'android' | 'electron' | 'web';\n\n/**\n * Result of getPluginPlatform(). Useful for validating that calls are routed\n * through the expected platform bridge.\n * @public\n */\nexport interface MdnsPluginPlatformResult {\n /** Platform implementation that produced this result. */\n platform: MdnsPluginPlatform;\n}\n\n/**\n * Normalized description of a discovered Bonjour/mDNS service.\n * Returned from {@link mDNSPlugin.discover}.\n *\n * @remarks\n * - `hosts` contains resolved IPv4/IPv6 numeric addresses (no DNS names).\n * - IPv4 addresses precede IPv6; order within each family follows discovery order.\n * - Native IPv6 scope suffixes are preserved (`%<scope-id>` on iOS; the OS-provided scope on Android).\n * Electron may return link-local IPv6 without a scope; callers must not assume every address is reachable.\n * - Resolved TXT records are returned when present.\n * - `domain` is typically `\"local.\"`.\n *\n * @public\n */\nexport interface MdnsService {\n /** Instance name of the service (may be uniqued by the OS, e.g. \"My App (2)\"). */\n name: string;\n\n /** Full service type including the trailing dot, e.g. `\"_http._tcp.\"`. */\n type: string;\n\n /** Service domain; typically `\"local.\"`. */\n domain: string;\n\n /** Port the service advertises. */\n port: number;\n\n /**\n * Resolved numeric IP addresses, IPv4 first, then IPv6 with any available scope suffix.\n * @example\n * `[\"192.168.1.42\", \"fe80::1234:abcd:...\"]`\n */\n hosts: string[];\n\n /** Host name when supplied by the platform, e.g. `\"my-device.local.\"`. */\n hostname?: string;\n\n /**\n * TXT dictionary (key → value).\n * @remarks Not all services publish TXT data.\n */\n txt?: MdnsTxt;\n}\n\n/**\n * Options for starting a Bonjour/mDNS advertisement.\n *\n * @remarks\n * - Service types accept an optional trailing dot; results always include it.\n * - Instance `name` should be short and human-readable; the OS may append `\" (n)\"` to ensure uniqueness.\n * Electron rejects a name conflict instead of renaming the service.\n * - Advertising TXT is supported on iOS, Android and Electron. Invalid input preserves the active advertisement.\n * - Native implementations guard publish with a timeout and return `error: true` instead of\n * leaving the Promise pending when the OS does not deliver a publish callback.\n * - Only one advertisement is active at a time. Starting a new one stops the previous one first.\n *\n * @public\n */\nexport interface MdnsBroadcastOptions {\n /**\n * Service type (including the trailing dot).\n * @defaultValue `\"_http._tcp.\"`\n * @example `\"_myapp._tcp.\"`\n */\n type?: string;\n\n /**\n * Service instance name (maximum 63 UTF-8 bytes). Defaults to `DevIOArtsMDNS`.\n */\n name?: string;\n\n /**\n * TCP port to advertise.\n * @remarks Must be a positive integer (1–65535).\n */\n port: number;\n\n /**\n * Optional TXT key–value pairs (UTF-8 strings).\n * @remarks Keys must be unique ignoring case, nonempty printable ASCII without `=`. Each `key=value` entry must fit in 255 UTF-8 bytes. The complete record is limited to 1300 bytes including length prefixes. Non-string values are rejected.\n */\n txt?: MdnsTxt;\n}\n\n/**\n * Options for Bonjour/mDNS discovery.\n *\n * @remarks\n * - The `name` filter matches the normalized name and also accepts prefix matches\n * (to handle OS-added `\" (n)\"` suffixes).\n * - When `useNW` is `true` on iOS, discovery uses `NWBrowser` for better P2P behavior.\n * - A valid new discovery replaces the previous request with an error on every platform.\n * - Dots and hyphens are equivalent when matching names; returned names retain their advertised spelling.\n * - Without a name filter, browsing continues for the entire timeout. With a filter it may finish once a matching IP address resolves.\n *\n * @public\n */\nexport interface MdnsDiscoverOptions {\n /**\n * Service type (including the trailing dot).\n * @defaultValue `\"_http._tcp.\"`\n * @example `\"_comm._tcp.\"`\n */\n type?: string;\n\n /**\n * Optional instance name filter (prefix-safe).\n * @example `\"MyAppName\"`\n */\n name?: string;\n\n /**\n * Discovery timeout in milliseconds. Finite numbers only; fractions are truncated and the delay is clamped to 0–2147483647.\n * @defaultValue `3000`\n */\n timeout?: number;\n\n /**\n * iOS-only hint to use `NWBrowser` instead of `NetServiceBrowser`.\n * @defaultValue `true`\n */\n useNW?: boolean;\n}\n\n/**\n * Result of startBroadcast(). Indicates whether advertising is active\n * and the final service name. On failure, `error` is true and `errorMessage`\n * describes the issue.\n * @public\n */\nexport interface MdnsBroadcastResult {\n /** True if the operation failed. */\n error: boolean;\n /** Error description or null on success. */\n errorMessage: string | null;\n /** Final (possibly uniquified) service instance name. Empty on failure. */\n name: string;\n /** Whether an advertiser is active, or may still be active after failed cleanup. */\n publishing: boolean;\n}\n\n/**\n * Result of discover(). Contains normalized services and error information.\n * @public\n */\nexport interface MdnsDiscoverResult {\n /** True if discovery encountered an error (partial results may still be present). */\n error: boolean;\n /** Error description or null when no error occurred. */\n errorMessage: string | null;\n /** Convenience count equal to services.length. */\n servicesFound: number;\n /** Resolved services with numeric addresses. Empty on error; partial results are discarded. */\n services: MdnsService[];\n}\n\n/**\n * Result of stopBroadcast(). Indicates whether the advertiser is active\n * after the call (normally false) and includes error information.\n * @public\n */\nexport interface MdnsStopResult {\n /** True if an error occurred while stopping. */\n error: boolean;\n /** Error description or null on success. */\n errorMessage: string | null;\n /** False after confirmed stop; true when stopping failed and the advertiser may still be active. */\n publishing: boolean;\n}\n\n/** Options for continuous discovery on iOS, Android and Electron. */\nexport interface MdnsWatchOptions {\n /** Nonempty list of service types. Trailing dots are optional; duplicates are merged. */\n types: string[];\n}\n\n/** Native browsers have been requested; later failures are reported through `watchError`. */\nexport interface MdnsWatchResult {\n error: boolean;\n errorMessage: string | null;\n watchersStarted: number;\n}\n\n/** Stops watching independently of any active broadcast. */\nexport interface MdnsWatchStopResult {\n error: boolean;\n errorMessage: string | null;\n watching: boolean;\n}\n\n/** Both found and lost events contain a complete service snapshot, including `hosts`. */\nexport interface MdnsServiceEvent {\n service: MdnsService;\n}\n\n/** Browser failures stop the watch; exhausted service resolution retries leave it running. */\nexport interface MdnsWatchErrorEvent {\n type: string;\n errorMessage: string;\n watching: boolean;\n}\n\n/**\n * Public API surface of the Capacitor mDNS plugin.\n *\n * @example\n * ```ts\n * import { mDNS } from 'capacitor-mdns';\n *\n * // Start advertising\n * await mDNS.startBroadcast({ type: '_http._tcp.', name: 'my.app.id', port: 9235 });\n *\n * // Discover services\n * const { services } = await mDNS.discover({ type: '_http._tcp.', timeout: 3000 });\n *\n * // Stop advertising\n * await mDNS.stopBroadcast();\n * ```\n *\n * @public\n */\nexport interface mDNSPlugin {\n /**\n * Return the platform implementation currently serving plugin calls.\n *\n * @returns Promise resolving to `MdnsPluginPlatformResult`.\n */\n getPluginPlatform(): Promise<MdnsPluginPlatformResult>;\n\n /**\n * Start advertising a Bonjour/mDNS service.\n *\n * @param options - {@link MdnsBroadcastOptions}\n * @returns Promise resolving to `MdnsBroadcastResult` (`true` on success).\n */\n startBroadcast(options: MdnsBroadcastOptions): Promise<MdnsBroadcastResult>;\n\n /**\n * Stop advertising the currently registered service (no-op if none).\n *\n * @returns Promise resolving to `MdnsStopResult`.\n * @remarks The `publishing` flag may be `false` after a successful stop.\n * Stopping is idempotent and is safe to call even if publishing never fully started.\n */\n stopBroadcast(): Promise<MdnsStopResult>;\n\n /**\n * Discover services of a given type and optionally filter by instance name.\n *\n * @param options - {@link MdnsDiscoverOptions}\n * @returns Promise resolving to `MdnsDiscoverResult`.\n * @remarks The result list is normalized across platforms.\n */\n discover(options?: MdnsDiscoverOptions): Promise<MdnsDiscoverResult>;\n\n /**\n * Continuously watch several service types. A valid call replaces the previous watch.\n * Register listeners before starting. Each resolved service emits `serviceFound` once;\n * disappearance emits `serviceLost` with its last snapshot. No loss is emitted for an\n * unresolved service. Watching and one-shot discovery can run together.\n * Thanks to Idrimi for contributing the original continuous discovery feature (PR #7).\n */\n watchServices(options: MdnsWatchOptions): Promise<MdnsWatchResult>;\n\n /** Stop all watchers. No events from that watch are emitted after this resolves. */\n stopWatching(): Promise<MdnsWatchStopResult>;\n\n addListener(\n eventName: 'serviceFound' | 'serviceLost',\n handler: (event: MdnsServiceEvent) => void,\n ): Promise<PluginListenerHandle>;\n addListener(eventName: 'watchError', handler: (event: MdnsWatchErrorEvent) => void): Promise<PluginListenerHandle>;\n removeAllListeners(): Promise<void>;\n}\n"]}
package/dist/esm/index.js CHANGED
@@ -1,7 +1,27 @@
1
1
  import { registerPlugin } from '@capacitor/core';
2
- const mDNS = registerPlugin('mDNS', {
2
+ const platformPlugin = registerPlugin('mDNS', {
3
3
  web: () => import('./web').then((m) => new m.mDNSWeb()),
4
- electron: () => Promise.resolve(window.CapacitorCustomPlatform.plugins.mDNS),
4
+ electron: () => {
5
+ var _a, _b;
6
+ const plugin = (_b = (_a = window.CapacitorCustomPlatform) === null || _a === void 0 ? void 0 : _a.plugins) === null || _b === void 0 ? void 0 : _b.mDNS;
7
+ if (!plugin)
8
+ throw new Error('mDNS Electron plugin is not registered; run npx cap-electron sync in the app');
9
+ return Promise.resolve(plugin);
10
+ },
11
+ });
12
+ const mDNS = new Proxy(platformPlugin, {
13
+ get(target, property, receiver) {
14
+ if (property !== 'discover')
15
+ return Reflect.get(target, property, receiver);
16
+ return (options) => {
17
+ const timeout = options === null || options === void 0 ? void 0 : options.timeout;
18
+ // Native JSON bridges turn NaN/Infinity into null, losing the invalid input.
19
+ if (timeout != null && (typeof timeout !== 'number' || !Number.isFinite(timeout))) {
20
+ return Promise.resolve({ error: true, errorMessage: 'Invalid timeout', servicesFound: 0, services: [] });
21
+ }
22
+ return target.discover(options);
23
+ };
24
+ },
5
25
  });
6
26
  export * from './definitions';
7
27
  export { mDNS };
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAIjD,MAAM,IAAI,GAAG,cAAc,CAAa,MAAM,EAAE;IAC9C,GAAG,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,CAAC;IACvD,QAAQ,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,CAAE,MAAc,CAAC,uBAAuB,CAAC,OAAO,CAAC,IAAkB,CAAC;CACpG,CAAC,CAAC;AAEH,cAAc,eAAe,CAAC;AAC9B,OAAO,EAAE,IAAI,EAAE,CAAC","sourcesContent":["import { registerPlugin } from '@capacitor/core';\n\nimport type { mDNSPlugin } from './definitions';\n\nconst mDNS = registerPlugin<mDNSPlugin>('mDNS', {\n web: () => import('./web').then((m) => new m.mDNSWeb()),\n electron: () => Promise.resolve((window as any).CapacitorCustomPlatform.plugins.mDNS as mDNSPlugin),\n});\n\nexport * from './definitions';\nexport { mDNS };\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAIjD,MAAM,cAAc,GAAG,cAAc,CAAa,MAAM,EAAE;IACxD,GAAG,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,CAAC;IACvD,QAAQ,EAAE,GAAG,EAAE;;QACb,MAAM,MAAM,GAAG,MAAA,MAAC,MAAc,CAAC,uBAAuB,0CAAE,OAAO,0CAAE,IAA8B,CAAC;QAChG,IAAI,CAAC,MAAM;YAAE,MAAM,IAAI,KAAK,CAAC,8EAA8E,CAAC,CAAC;QAC7G,OAAO,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IACjC,CAAC;CACF,CAAC,CAAC;AAEH,MAAM,IAAI,GAAG,IAAI,KAAK,CAAC,cAAc,EAAE;IACrC,GAAG,CAAC,MAAM,EAAE,QAAQ,EAAE,QAAQ;QAC5B,IAAI,QAAQ,KAAK,UAAU;YAAE,OAAO,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC;QAC5E,OAAO,CAAC,OAA6B,EAAE,EAAE;YACvC,MAAM,OAAO,GAAG,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,OAAO,CAAC;YACjC,6EAA6E;YAC7E,IAAI,OAAO,IAAI,IAAI,IAAI,CAAC,OAAO,OAAO,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC;gBAClF,OAAO,OAAO,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,YAAY,EAAE,iBAAiB,EAAE,aAAa,EAAE,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,CAAC;YAC3G,CAAC;YACD,OAAO,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QAClC,CAAC,CAAC;IACJ,CAAC;CACF,CAAC,CAAC;AAEH,cAAc,eAAe,CAAC;AAC9B,OAAO,EAAE,IAAI,EAAE,CAAC","sourcesContent":["import { registerPlugin } from '@capacitor/core';\n\nimport type { MdnsDiscoverOptions, mDNSPlugin } from './definitions';\n\nconst platformPlugin = registerPlugin<mDNSPlugin>('mDNS', {\n web: () => import('./web').then((m) => new m.mDNSWeb()),\n electron: () => {\n const plugin = (window as any).CapacitorCustomPlatform?.plugins?.mDNS as mDNSPlugin | undefined;\n if (!plugin) throw new Error('mDNS Electron plugin is not registered; run npx cap-electron sync in the app');\n return Promise.resolve(plugin);\n },\n});\n\nconst mDNS = new Proxy(platformPlugin, {\n get(target, property, receiver) {\n if (property !== 'discover') return Reflect.get(target, property, receiver);\n return (options?: MdnsDiscoverOptions) => {\n const timeout = options?.timeout;\n // Native JSON bridges turn NaN/Infinity into null, losing the invalid input.\n if (timeout != null && (typeof timeout !== 'number' || !Number.isFinite(timeout))) {\n return Promise.resolve({ error: true, errorMessage: 'Invalid timeout', servicesFound: 0, services: [] });\n }\n return target.discover(options);\n };\n },\n});\n\nexport * from './definitions';\nexport { mDNS };\n"]}
package/dist/esm/web.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import { WebPlugin } from '@capacitor/core';
2
- import type { mDNSPlugin, MdnsBroadcastOptions, MdnsDiscoverOptions, MdnsBroadcastResult, MdnsStopResult, MdnsDiscoverResult, MdnsPluginPlatformResult } from './definitions';
2
+ import type { PluginListenerHandle } from '@capacitor/core';
3
+ import type { mDNSPlugin, MdnsBroadcastOptions, MdnsDiscoverOptions, MdnsBroadcastResult, MdnsStopResult, MdnsDiscoverResult, MdnsPluginPlatformResult, MdnsWatchOptions, MdnsWatchResult, MdnsWatchStopResult } from './definitions';
3
4
  /**
4
5
  * Web implementation of the mDNS plugin.
5
6
  *
@@ -16,4 +17,8 @@ export declare class mDNSWeb extends WebPlugin implements mDNSPlugin {
16
17
  startBroadcast(options: MdnsBroadcastOptions): Promise<MdnsBroadcastResult>;
17
18
  stopBroadcast(): Promise<MdnsStopResult>;
18
19
  discover(options?: MdnsDiscoverOptions): Promise<MdnsDiscoverResult>;
20
+ watchServices(options: MdnsWatchOptions): Promise<MdnsWatchResult>;
21
+ stopWatching(): Promise<MdnsWatchStopResult>;
22
+ addListener(eventName: string, handler: (data: any) => void): Promise<PluginListenerHandle>;
23
+ removeAllListeners(): Promise<void>;
19
24
  }
package/dist/esm/web.js CHANGED
@@ -46,5 +46,28 @@ export class mDNSWeb extends WebPlugin {
46
46
  console.log('[WEB_NOT_SUPPORTED] discover', options);
47
47
  return { services: [], error: true, errorMessage: this.unsupportedMessage, servicesFound: 0 };
48
48
  }
49
+ async watchServices(options) {
50
+ var _a;
51
+ if ((_a = this.electronApi) === null || _a === void 0 ? void 0 : _a.watchServices)
52
+ return this.electronApi.watchServices(options);
53
+ return { error: true, errorMessage: this.unsupportedMessage, watchersStarted: 0 };
54
+ }
55
+ async stopWatching() {
56
+ var _a;
57
+ if ((_a = this.electronApi) === null || _a === void 0 ? void 0 : _a.stopWatching)
58
+ return this.electronApi.stopWatching();
59
+ return { watching: false, error: false, errorMessage: null };
60
+ }
61
+ async addListener(eventName, handler) {
62
+ var _a;
63
+ if ((_a = this.electronApi) === null || _a === void 0 ? void 0 : _a.addListener)
64
+ return this.electronApi.addListener(eventName, handler);
65
+ return super.addListener(eventName, handler);
66
+ }
67
+ async removeAllListeners() {
68
+ var _a, _b;
69
+ await ((_b = (_a = this.electronApi) === null || _a === void 0 ? void 0 : _a.removeAllListeners) === null || _b === void 0 ? void 0 : _b.call(_a));
70
+ await super.removeAllListeners();
71
+ }
49
72
  }
50
73
  //# sourceMappingURL=web.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"web.js","sourceRoot":"","sources":["../../src/web.ts"],"names":[],"mappings":"AAAA,aAAa;AACb,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAY5C;;;;;;;GAOG;AACH,MAAM,OAAO,OAAQ,SAAQ,SAAS;IAAtC;;QACmB,uBAAkB,GAAG,+CAA+C,CAAC;IAyCxF,CAAC;IAvCC,4CAA4C;IAC5C,IAAY,WAAW;QAQrB,IAAI,OAAO,MAAM,KAAK,WAAW;YAAE,OAAO,SAAS,CAAC;QACpD,OAAQ,MAAc,CAAC,IAAI,IAAK,MAAc,CAAC,IAAI,CAAC;IACtD,CAAC;IAED,KAAK,CAAC,iBAAiB;QACrB,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW,CAAC;QAC7B,IAAI,GAAG,aAAH,GAAG,uBAAH,GAAG,CAAE,iBAAiB;YAAE,OAAO,GAAG,CAAC,iBAAiB,EAAE,CAAC;QAC3D,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;IAC7B,CAAC;IAED,KAAK,CAAC,cAAc,CAAC,OAA6B;QAChD,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW,CAAC;QAC7B,IAAI,GAAG,aAAH,GAAG,uBAAH,GAAG,CAAE,cAAc;YAAE,OAAO,GAAG,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;QAC5D,OAAO,CAAC,GAAG,CAAC,oCAAoC,EAAE,OAAO,CAAC,CAAC;QAC3D,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,CAAC,kBAAkB,EAAE,CAAC;IAC7F,CAAC;IAED,KAAK,CAAC,aAAa;QACjB,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW,CAAC;QAC7B,IAAI,GAAG,aAAH,GAAG,uBAAH,GAAG,CAAE,aAAa;YAAE,OAAO,GAAG,CAAC,aAAa,EAAE,CAAC;QACnD,OAAO,CAAC,GAAG,CAAC,mCAAmC,CAAC,CAAC;QACjD,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC;IACjE,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,UAA+B,EAAE;QAC9C,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW,CAAC;QAC7B,IAAI,GAAG,aAAH,GAAG,uBAAH,GAAG,CAAE,QAAQ;YAAE,OAAO,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QAChD,OAAO,CAAC,GAAG,CAAC,8BAA8B,EAAE,OAAO,CAAC,CAAC;QACrD,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,CAAC,kBAAkB,EAAE,aAAa,EAAE,CAAC,EAAE,CAAC;IAChG,CAAC;CACF","sourcesContent":["// src/web.ts\nimport { WebPlugin } from '@capacitor/core';\n\nimport type {\n mDNSPlugin,\n MdnsBroadcastOptions,\n MdnsDiscoverOptions,\n MdnsBroadcastResult,\n MdnsStopResult,\n MdnsDiscoverResult,\n MdnsPluginPlatformResult,\n} from './definitions';\n\n/**\n * Web implementation of the mDNS plugin.\n *\n * This class behaves as a thin proxy:\n * - In Electron (when a preload exposes window.mDNS/window.mdns), calls are forwarded over IPC.\n * - In a regular browser, mDNS is not available; methods resolve with well-shaped stub values\n * and log a console message with the [WEB_NOT_SUPPORTED] tag.\n */\nexport class mDNSWeb extends WebPlugin implements mDNSPlugin {\n private readonly unsupportedMessage = 'mDNS is not supported in this browser runtime';\n\n /** Electron preload bridge (if present). */\n private get electronApi():\n | undefined\n | {\n startBroadcast(o: MdnsBroadcastOptions): Promise<MdnsBroadcastResult>;\n stopBroadcast(): Promise<MdnsStopResult>;\n discover(o?: MdnsDiscoverOptions): Promise<MdnsDiscoverResult>;\n getPluginPlatform?(): Promise<MdnsPluginPlatformResult>;\n } {\n if (typeof window === 'undefined') return undefined;\n return (window as any).mDNS || (window as any).mdns;\n }\n\n async getPluginPlatform(): Promise<MdnsPluginPlatformResult> {\n const api = this.electronApi;\n if (api?.getPluginPlatform) return api.getPluginPlatform();\n return { platform: 'web' };\n }\n\n async startBroadcast(options: MdnsBroadcastOptions): Promise<MdnsBroadcastResult> {\n const api = this.electronApi;\n if (api?.startBroadcast) return api.startBroadcast(options);\n console.log('[WEB_NOT_SUPPORTED] startBroadcast', options);\n return { publishing: false, name: '', error: true, errorMessage: this.unsupportedMessage };\n }\n\n async stopBroadcast(): Promise<MdnsStopResult> {\n const api = this.electronApi;\n if (api?.stopBroadcast) return api.stopBroadcast();\n console.log('[WEB_NOT_SUPPORTED] stopBroadcast');\n return { publishing: false, error: false, errorMessage: null };\n }\n\n async discover(options: MdnsDiscoverOptions = {}): Promise<MdnsDiscoverResult> {\n const api = this.electronApi;\n if (api?.discover) return api.discover(options);\n console.log('[WEB_NOT_SUPPORTED] discover', options);\n return { services: [], error: true, errorMessage: this.unsupportedMessage, servicesFound: 0 };\n }\n}\n"]}
1
+ {"version":3,"file":"web.js","sourceRoot":"","sources":["../../src/web.ts"],"names":[],"mappings":"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","sourcesContent":["// src/web.ts\nimport { WebPlugin } from '@capacitor/core';\nimport type { PluginListenerHandle } from '@capacitor/core';\n\nimport type {\n mDNSPlugin,\n MdnsBroadcastOptions,\n MdnsDiscoverOptions,\n MdnsBroadcastResult,\n MdnsStopResult,\n MdnsDiscoverResult,\n MdnsPluginPlatformResult,\n MdnsWatchOptions,\n MdnsWatchResult,\n MdnsWatchStopResult,\n} from './definitions';\n\n/**\n * Web implementation of the mDNS plugin.\n *\n * This class behaves as a thin proxy:\n * - In Electron (when a preload exposes window.mDNS/window.mdns), calls are forwarded over IPC.\n * - In a regular browser, mDNS is not available; methods resolve with well-shaped stub values\n * and log a console message with the [WEB_NOT_SUPPORTED] tag.\n */\nexport class mDNSWeb extends WebPlugin implements mDNSPlugin {\n private readonly unsupportedMessage = 'mDNS is not supported in this browser runtime';\n\n /** Electron preload bridge (if present). */\n private get electronApi():\n | undefined\n | {\n startBroadcast(o: MdnsBroadcastOptions): Promise<MdnsBroadcastResult>;\n stopBroadcast(): Promise<MdnsStopResult>;\n discover(o?: MdnsDiscoverOptions): Promise<MdnsDiscoverResult>;\n getPluginPlatform?(): Promise<MdnsPluginPlatformResult>;\n watchServices?(options: MdnsWatchOptions): Promise<MdnsWatchResult>;\n stopWatching?(): Promise<MdnsWatchStopResult>;\n addListener?(eventName: string, handler: (data: any) => void): Promise<PluginListenerHandle>;\n removeAllListeners?(): Promise<void>;\n } {\n if (typeof window === 'undefined') return undefined;\n return (window as any).mDNS || (window as any).mdns;\n }\n\n async getPluginPlatform(): Promise<MdnsPluginPlatformResult> {\n const api = this.electronApi;\n if (api?.getPluginPlatform) return api.getPluginPlatform();\n return { platform: 'web' };\n }\n\n async startBroadcast(options: MdnsBroadcastOptions): Promise<MdnsBroadcastResult> {\n const api = this.electronApi;\n if (api?.startBroadcast) return api.startBroadcast(options);\n console.log('[WEB_NOT_SUPPORTED] startBroadcast', options);\n return { publishing: false, name: '', error: true, errorMessage: this.unsupportedMessage };\n }\n\n async stopBroadcast(): Promise<MdnsStopResult> {\n const api = this.electronApi;\n if (api?.stopBroadcast) return api.stopBroadcast();\n console.log('[WEB_NOT_SUPPORTED] stopBroadcast');\n return { publishing: false, error: false, errorMessage: null };\n }\n\n async discover(options: MdnsDiscoverOptions = {}): Promise<MdnsDiscoverResult> {\n const api = this.electronApi;\n if (api?.discover) return api.discover(options);\n console.log('[WEB_NOT_SUPPORTED] discover', options);\n return { services: [], error: true, errorMessage: this.unsupportedMessage, servicesFound: 0 };\n }\n\n async watchServices(options: MdnsWatchOptions): Promise<MdnsWatchResult> {\n if (this.electronApi?.watchServices) return this.electronApi.watchServices(options);\n return { error: true, errorMessage: this.unsupportedMessage, watchersStarted: 0 };\n }\n\n async stopWatching(): Promise<MdnsWatchStopResult> {\n if (this.electronApi?.stopWatching) return this.electronApi.stopWatching();\n return { watching: false, error: false, errorMessage: null };\n }\n\n async addListener(eventName: string, handler: (data: any) => void): Promise<PluginListenerHandle> {\n if (this.electronApi?.addListener) return this.electronApi.addListener(eventName, handler);\n return super.addListener(eventName, handler);\n }\n\n async removeAllListeners(): Promise<void> {\n await this.electronApi?.removeAllListeners?.();\n await super.removeAllListeners();\n }\n}\n"]}
@@ -2,9 +2,29 @@
2
2
 
3
3
  var core = require('@capacitor/core');
4
4
 
5
- const mDNS = core.registerPlugin('mDNS', {
5
+ const platformPlugin = core.registerPlugin('mDNS', {
6
6
  web: () => Promise.resolve().then(function () { return web; }).then((m) => new m.mDNSWeb()),
7
- electron: () => Promise.resolve(window.CapacitorCustomPlatform.plugins.mDNS),
7
+ electron: () => {
8
+ var _a, _b;
9
+ const plugin = (_b = (_a = window.CapacitorCustomPlatform) === null || _a === void 0 ? void 0 : _a.plugins) === null || _b === void 0 ? void 0 : _b.mDNS;
10
+ if (!plugin)
11
+ throw new Error('mDNS Electron plugin is not registered; run npx cap-electron sync in the app');
12
+ return Promise.resolve(plugin);
13
+ },
14
+ });
15
+ const mDNS = new Proxy(platformPlugin, {
16
+ get(target, property, receiver) {
17
+ if (property !== 'discover')
18
+ return Reflect.get(target, property, receiver);
19
+ return (options) => {
20
+ const timeout = options === null || options === void 0 ? void 0 : options.timeout;
21
+ // Native JSON bridges turn NaN/Infinity into null, losing the invalid input.
22
+ if (timeout != null && (typeof timeout !== 'number' || !Number.isFinite(timeout))) {
23
+ return Promise.resolve({ error: true, errorMessage: 'Invalid timeout', servicesFound: 0, services: [] });
24
+ }
25
+ return target.discover(options);
26
+ };
27
+ },
8
28
  });
9
29
 
10
30
  // src/web.ts
@@ -54,6 +74,29 @@ class mDNSWeb extends core.WebPlugin {
54
74
  console.log('[WEB_NOT_SUPPORTED] discover', options);
55
75
  return { services: [], error: true, errorMessage: this.unsupportedMessage, servicesFound: 0 };
56
76
  }
77
+ async watchServices(options) {
78
+ var _a;
79
+ if ((_a = this.electronApi) === null || _a === void 0 ? void 0 : _a.watchServices)
80
+ return this.electronApi.watchServices(options);
81
+ return { error: true, errorMessage: this.unsupportedMessage, watchersStarted: 0 };
82
+ }
83
+ async stopWatching() {
84
+ var _a;
85
+ if ((_a = this.electronApi) === null || _a === void 0 ? void 0 : _a.stopWatching)
86
+ return this.electronApi.stopWatching();
87
+ return { watching: false, error: false, errorMessage: null };
88
+ }
89
+ async addListener(eventName, handler) {
90
+ var _a;
91
+ if ((_a = this.electronApi) === null || _a === void 0 ? void 0 : _a.addListener)
92
+ return this.electronApi.addListener(eventName, handler);
93
+ return super.addListener(eventName, handler);
94
+ }
95
+ async removeAllListeners() {
96
+ var _a, _b;
97
+ await ((_b = (_a = this.electronApi) === null || _a === void 0 ? void 0 : _a.removeAllListeners) === null || _b === void 0 ? void 0 : _b.call(_a));
98
+ await super.removeAllListeners();
99
+ }
57
100
  }
58
101
 
59
102
  var web = /*#__PURE__*/Object.freeze({
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.cjs.js","sources":["esm/index.js","esm/web.js"],"sourcesContent":["import { registerPlugin } from '@capacitor/core';\nconst mDNS = registerPlugin('mDNS', {\n web: () => import('./web').then((m) => new m.mDNSWeb()),\n electron: () => Promise.resolve(window.CapacitorCustomPlatform.plugins.mDNS),\n});\nexport * from './definitions';\nexport { mDNS };\n//# sourceMappingURL=index.js.map","// src/web.ts\nimport { WebPlugin } from '@capacitor/core';\n/**\n * Web implementation of the mDNS plugin.\n *\n * This class behaves as a thin proxy:\n * - In Electron (when a preload exposes window.mDNS/window.mdns), calls are forwarded over IPC.\n * - In a regular browser, mDNS is not available; methods resolve with well-shaped stub values\n * and log a console message with the [WEB_NOT_SUPPORTED] tag.\n */\nexport class mDNSWeb extends WebPlugin {\n constructor() {\n super(...arguments);\n this.unsupportedMessage = 'mDNS is not supported in this browser runtime';\n }\n /** Electron preload bridge (if present). */\n get electronApi() {\n if (typeof window === 'undefined')\n return undefined;\n return window.mDNS || window.mdns;\n }\n async getPluginPlatform() {\n const api = this.electronApi;\n if (api === null || api === void 0 ? void 0 : api.getPluginPlatform)\n return api.getPluginPlatform();\n return { platform: 'web' };\n }\n async startBroadcast(options) {\n const api = this.electronApi;\n if (api === null || api === void 0 ? void 0 : api.startBroadcast)\n return api.startBroadcast(options);\n console.log('[WEB_NOT_SUPPORTED] startBroadcast', options);\n return { publishing: false, name: '', error: true, errorMessage: this.unsupportedMessage };\n }\n async stopBroadcast() {\n const api = this.electronApi;\n if (api === null || api === void 0 ? void 0 : api.stopBroadcast)\n return api.stopBroadcast();\n console.log('[WEB_NOT_SUPPORTED] stopBroadcast');\n return { publishing: false, error: false, errorMessage: null };\n }\n async discover(options = {}) {\n const api = this.electronApi;\n if (api === null || api === void 0 ? void 0 : api.discover)\n return api.discover(options);\n console.log('[WEB_NOT_SUPPORTED] discover', options);\n return { services: [], error: true, errorMessage: this.unsupportedMessage, servicesFound: 0 };\n }\n}\n//# sourceMappingURL=web.js.map"],"names":["registerPlugin","WebPlugin"],"mappings":";;;;AACK,MAAC,IAAI,GAAGA,mBAAc,CAAC,MAAM,EAAE;AACpC,IAAI,GAAG,EAAE,MAAM,mDAAe,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,OAAO,EAAE,CAAC;AAC3D,IAAI,QAAQ,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,uBAAuB,CAAC,OAAO,CAAC,IAAI,CAAC;AAChF,CAAC;;ACJD;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,MAAM,OAAO,SAASC,cAAS,CAAC;AACvC,IAAI,WAAW,GAAG;AAClB,QAAQ,KAAK,CAAC,GAAG,SAAS,CAAC;AAC3B,QAAQ,IAAI,CAAC,kBAAkB,GAAG,+CAA+C;AACjF,IAAI;AACJ;AACA,IAAI,IAAI,WAAW,GAAG;AACtB,QAAQ,IAAI,OAAO,MAAM,KAAK,WAAW;AACzC,YAAY,OAAO,SAAS;AAC5B,QAAQ,OAAO,MAAM,CAAC,IAAI,IAAI,MAAM,CAAC,IAAI;AACzC,IAAI;AACJ,IAAI,MAAM,iBAAiB,GAAG;AAC9B,QAAQ,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW;AACpC,QAAQ,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,MAAM,GAAG,MAAM,GAAG,GAAG,CAAC,iBAAiB;AAC3E,YAAY,OAAO,GAAG,CAAC,iBAAiB,EAAE;AAC1C,QAAQ,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE;AAClC,IAAI;AACJ,IAAI,MAAM,cAAc,CAAC,OAAO,EAAE;AAClC,QAAQ,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW;AACpC,QAAQ,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,MAAM,GAAG,MAAM,GAAG,GAAG,CAAC,cAAc;AACxE,YAAY,OAAO,GAAG,CAAC,cAAc,CAAC,OAAO,CAAC;AAC9C,QAAQ,OAAO,CAAC,GAAG,CAAC,oCAAoC,EAAE,OAAO,CAAC;AAClE,QAAQ,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,CAAC,kBAAkB,EAAE;AAClG,IAAI;AACJ,IAAI,MAAM,aAAa,GAAG;AAC1B,QAAQ,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW;AACpC,QAAQ,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,MAAM,GAAG,MAAM,GAAG,GAAG,CAAC,aAAa;AACvE,YAAY,OAAO,GAAG,CAAC,aAAa,EAAE;AACtC,QAAQ,OAAO,CAAC,GAAG,CAAC,mCAAmC,CAAC;AACxD,QAAQ,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE;AACtE,IAAI;AACJ,IAAI,MAAM,QAAQ,CAAC,OAAO,GAAG,EAAE,EAAE;AACjC,QAAQ,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW;AACpC,QAAQ,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,MAAM,GAAG,MAAM,GAAG,GAAG,CAAC,QAAQ;AAClE,YAAY,OAAO,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC;AACxC,QAAQ,OAAO,CAAC,GAAG,CAAC,8BAA8B,EAAE,OAAO,CAAC;AAC5D,QAAQ,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,CAAC,kBAAkB,EAAE,aAAa,EAAE,CAAC,EAAE;AACrG,IAAI;AACJ;;;;;;;;;"}
1
+ {"version":3,"file":"plugin.cjs.js","sources":["esm/index.js","esm/web.js"],"sourcesContent":["import { registerPlugin } from '@capacitor/core';\nconst platformPlugin = registerPlugin('mDNS', {\n web: () => import('./web').then((m) => new m.mDNSWeb()),\n electron: () => {\n var _a, _b;\n const plugin = (_b = (_a = window.CapacitorCustomPlatform) === null || _a === void 0 ? void 0 : _a.plugins) === null || _b === void 0 ? void 0 : _b.mDNS;\n if (!plugin)\n throw new Error('mDNS Electron plugin is not registered; run npx cap-electron sync in the app');\n return Promise.resolve(plugin);\n },\n});\nconst mDNS = new Proxy(platformPlugin, {\n get(target, property, receiver) {\n if (property !== 'discover')\n return Reflect.get(target, property, receiver);\n return (options) => {\n const timeout = options === null || options === void 0 ? void 0 : options.timeout;\n // Native JSON bridges turn NaN/Infinity into null, losing the invalid input.\n if (timeout != null && (typeof timeout !== 'number' || !Number.isFinite(timeout))) {\n return Promise.resolve({ error: true, errorMessage: 'Invalid timeout', servicesFound: 0, services: [] });\n }\n return target.discover(options);\n };\n },\n});\nexport * from './definitions';\nexport { mDNS };\n//# sourceMappingURL=index.js.map","// src/web.ts\nimport { WebPlugin } from '@capacitor/core';\n/**\n * Web implementation of the mDNS plugin.\n *\n * This class behaves as a thin proxy:\n * - In Electron (when a preload exposes window.mDNS/window.mdns), calls are forwarded over IPC.\n * - In a regular browser, mDNS is not available; methods resolve with well-shaped stub values\n * and log a console message with the [WEB_NOT_SUPPORTED] tag.\n */\nexport class mDNSWeb extends WebPlugin {\n constructor() {\n super(...arguments);\n this.unsupportedMessage = 'mDNS is not supported in this browser runtime';\n }\n /** Electron preload bridge (if present). */\n get electronApi() {\n if (typeof window === 'undefined')\n return undefined;\n return window.mDNS || window.mdns;\n }\n async getPluginPlatform() {\n const api = this.electronApi;\n if (api === null || api === void 0 ? void 0 : api.getPluginPlatform)\n return api.getPluginPlatform();\n return { platform: 'web' };\n }\n async startBroadcast(options) {\n const api = this.electronApi;\n if (api === null || api === void 0 ? void 0 : api.startBroadcast)\n return api.startBroadcast(options);\n console.log('[WEB_NOT_SUPPORTED] startBroadcast', options);\n return { publishing: false, name: '', error: true, errorMessage: this.unsupportedMessage };\n }\n async stopBroadcast() {\n const api = this.electronApi;\n if (api === null || api === void 0 ? void 0 : api.stopBroadcast)\n return api.stopBroadcast();\n console.log('[WEB_NOT_SUPPORTED] stopBroadcast');\n return { publishing: false, error: false, errorMessage: null };\n }\n async discover(options = {}) {\n const api = this.electronApi;\n if (api === null || api === void 0 ? void 0 : api.discover)\n return api.discover(options);\n console.log('[WEB_NOT_SUPPORTED] discover', options);\n return { services: [], error: true, errorMessage: this.unsupportedMessage, servicesFound: 0 };\n }\n async watchServices(options) {\n var _a;\n if ((_a = this.electronApi) === null || _a === void 0 ? void 0 : _a.watchServices)\n return this.electronApi.watchServices(options);\n return { error: true, errorMessage: this.unsupportedMessage, watchersStarted: 0 };\n }\n async stopWatching() {\n var _a;\n if ((_a = this.electronApi) === null || _a === void 0 ? void 0 : _a.stopWatching)\n return this.electronApi.stopWatching();\n return { watching: false, error: false, errorMessage: null };\n }\n async addListener(eventName, handler) {\n var _a;\n if ((_a = this.electronApi) === null || _a === void 0 ? void 0 : _a.addListener)\n return this.electronApi.addListener(eventName, handler);\n return super.addListener(eventName, handler);\n }\n async removeAllListeners() {\n var _a, _b;\n await ((_b = (_a = this.electronApi) === null || _a === void 0 ? void 0 : _a.removeAllListeners) === null || _b === void 0 ? void 0 : _b.call(_a));\n await super.removeAllListeners();\n }\n}\n//# sourceMappingURL=web.js.map"],"names":["registerPlugin","WebPlugin"],"mappings":"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"}
package/dist/plugin.js CHANGED
@@ -1,9 +1,29 @@
1
1
  var capacitormDNS = (function (exports, core) {
2
2
  'use strict';
3
3
 
4
- const mDNS = core.registerPlugin('mDNS', {
4
+ const platformPlugin = core.registerPlugin('mDNS', {
5
5
  web: () => Promise.resolve().then(function () { return web; }).then((m) => new m.mDNSWeb()),
6
- electron: () => Promise.resolve(window.CapacitorCustomPlatform.plugins.mDNS),
6
+ electron: () => {
7
+ var _a, _b;
8
+ const plugin = (_b = (_a = window.CapacitorCustomPlatform) === null || _a === void 0 ? void 0 : _a.plugins) === null || _b === void 0 ? void 0 : _b.mDNS;
9
+ if (!plugin)
10
+ throw new Error('mDNS Electron plugin is not registered; run npx cap-electron sync in the app');
11
+ return Promise.resolve(plugin);
12
+ },
13
+ });
14
+ const mDNS = new Proxy(platformPlugin, {
15
+ get(target, property, receiver) {
16
+ if (property !== 'discover')
17
+ return Reflect.get(target, property, receiver);
18
+ return (options) => {
19
+ const timeout = options === null || options === void 0 ? void 0 : options.timeout;
20
+ // Native JSON bridges turn NaN/Infinity into null, losing the invalid input.
21
+ if (timeout != null && (typeof timeout !== 'number' || !Number.isFinite(timeout))) {
22
+ return Promise.resolve({ error: true, errorMessage: 'Invalid timeout', servicesFound: 0, services: [] });
23
+ }
24
+ return target.discover(options);
25
+ };
26
+ },
7
27
  });
8
28
 
9
29
  // src/web.ts
@@ -53,6 +73,29 @@ var capacitormDNS = (function (exports, core) {
53
73
  console.log('[WEB_NOT_SUPPORTED] discover', options);
54
74
  return { services: [], error: true, errorMessage: this.unsupportedMessage, servicesFound: 0 };
55
75
  }
76
+ async watchServices(options) {
77
+ var _a;
78
+ if ((_a = this.electronApi) === null || _a === void 0 ? void 0 : _a.watchServices)
79
+ return this.electronApi.watchServices(options);
80
+ return { error: true, errorMessage: this.unsupportedMessage, watchersStarted: 0 };
81
+ }
82
+ async stopWatching() {
83
+ var _a;
84
+ if ((_a = this.electronApi) === null || _a === void 0 ? void 0 : _a.stopWatching)
85
+ return this.electronApi.stopWatching();
86
+ return { watching: false, error: false, errorMessage: null };
87
+ }
88
+ async addListener(eventName, handler) {
89
+ var _a;
90
+ if ((_a = this.electronApi) === null || _a === void 0 ? void 0 : _a.addListener)
91
+ return this.electronApi.addListener(eventName, handler);
92
+ return super.addListener(eventName, handler);
93
+ }
94
+ async removeAllListeners() {
95
+ var _a, _b;
96
+ await ((_b = (_a = this.electronApi) === null || _a === void 0 ? void 0 : _a.removeAllListeners) === null || _b === void 0 ? void 0 : _b.call(_a));
97
+ await super.removeAllListeners();
98
+ }
56
99
  }
57
100
 
58
101
  var web = /*#__PURE__*/Object.freeze({
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.js","sources":["esm/index.js","esm/web.js"],"sourcesContent":["import { registerPlugin } from '@capacitor/core';\nconst mDNS = registerPlugin('mDNS', {\n web: () => import('./web').then((m) => new m.mDNSWeb()),\n electron: () => Promise.resolve(window.CapacitorCustomPlatform.plugins.mDNS),\n});\nexport * from './definitions';\nexport { mDNS };\n//# sourceMappingURL=index.js.map","// src/web.ts\nimport { WebPlugin } from '@capacitor/core';\n/**\n * Web implementation of the mDNS plugin.\n *\n * This class behaves as a thin proxy:\n * - In Electron (when a preload exposes window.mDNS/window.mdns), calls are forwarded over IPC.\n * - In a regular browser, mDNS is not available; methods resolve with well-shaped stub values\n * and log a console message with the [WEB_NOT_SUPPORTED] tag.\n */\nexport class mDNSWeb extends WebPlugin {\n constructor() {\n super(...arguments);\n this.unsupportedMessage = 'mDNS is not supported in this browser runtime';\n }\n /** Electron preload bridge (if present). */\n get electronApi() {\n if (typeof window === 'undefined')\n return undefined;\n return window.mDNS || window.mdns;\n }\n async getPluginPlatform() {\n const api = this.electronApi;\n if (api === null || api === void 0 ? void 0 : api.getPluginPlatform)\n return api.getPluginPlatform();\n return { platform: 'web' };\n }\n async startBroadcast(options) {\n const api = this.electronApi;\n if (api === null || api === void 0 ? void 0 : api.startBroadcast)\n return api.startBroadcast(options);\n console.log('[WEB_NOT_SUPPORTED] startBroadcast', options);\n return { publishing: false, name: '', error: true, errorMessage: this.unsupportedMessage };\n }\n async stopBroadcast() {\n const api = this.electronApi;\n if (api === null || api === void 0 ? void 0 : api.stopBroadcast)\n return api.stopBroadcast();\n console.log('[WEB_NOT_SUPPORTED] stopBroadcast');\n return { publishing: false, error: false, errorMessage: null };\n }\n async discover(options = {}) {\n const api = this.electronApi;\n if (api === null || api === void 0 ? void 0 : api.discover)\n return api.discover(options);\n console.log('[WEB_NOT_SUPPORTED] discover', options);\n return { services: [], error: true, errorMessage: this.unsupportedMessage, servicesFound: 0 };\n }\n}\n//# sourceMappingURL=web.js.map"],"names":["registerPlugin","WebPlugin"],"mappings":";;;AACK,UAAC,IAAI,GAAGA,mBAAc,CAAC,MAAM,EAAE;IACpC,IAAI,GAAG,EAAE,MAAM,mDAAe,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,OAAO,EAAE,CAAC;IAC3D,IAAI,QAAQ,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,uBAAuB,CAAC,OAAO,CAAC,IAAI,CAAC;IAChF,CAAC;;ICJD;IAEA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACO,MAAM,OAAO,SAASC,cAAS,CAAC;IACvC,IAAI,WAAW,GAAG;IAClB,QAAQ,KAAK,CAAC,GAAG,SAAS,CAAC;IAC3B,QAAQ,IAAI,CAAC,kBAAkB,GAAG,+CAA+C;IACjF,IAAI;IACJ;IACA,IAAI,IAAI,WAAW,GAAG;IACtB,QAAQ,IAAI,OAAO,MAAM,KAAK,WAAW;IACzC,YAAY,OAAO,SAAS;IAC5B,QAAQ,OAAO,MAAM,CAAC,IAAI,IAAI,MAAM,CAAC,IAAI;IACzC,IAAI;IACJ,IAAI,MAAM,iBAAiB,GAAG;IAC9B,QAAQ,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW;IACpC,QAAQ,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,MAAM,GAAG,MAAM,GAAG,GAAG,CAAC,iBAAiB;IAC3E,YAAY,OAAO,GAAG,CAAC,iBAAiB,EAAE;IAC1C,QAAQ,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE;IAClC,IAAI;IACJ,IAAI,MAAM,cAAc,CAAC,OAAO,EAAE;IAClC,QAAQ,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW;IACpC,QAAQ,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,MAAM,GAAG,MAAM,GAAG,GAAG,CAAC,cAAc;IACxE,YAAY,OAAO,GAAG,CAAC,cAAc,CAAC,OAAO,CAAC;IAC9C,QAAQ,OAAO,CAAC,GAAG,CAAC,oCAAoC,EAAE,OAAO,CAAC;IAClE,QAAQ,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,CAAC,kBAAkB,EAAE;IAClG,IAAI;IACJ,IAAI,MAAM,aAAa,GAAG;IAC1B,QAAQ,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW;IACpC,QAAQ,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,MAAM,GAAG,MAAM,GAAG,GAAG,CAAC,aAAa;IACvE,YAAY,OAAO,GAAG,CAAC,aAAa,EAAE;IACtC,QAAQ,OAAO,CAAC,GAAG,CAAC,mCAAmC,CAAC;IACxD,QAAQ,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE;IACtE,IAAI;IACJ,IAAI,MAAM,QAAQ,CAAC,OAAO,GAAG,EAAE,EAAE;IACjC,QAAQ,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW;IACpC,QAAQ,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,MAAM,GAAG,MAAM,GAAG,GAAG,CAAC,QAAQ;IAClE,YAAY,OAAO,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC;IACxC,QAAQ,OAAO,CAAC,GAAG,CAAC,8BAA8B,EAAE,OAAO,CAAC;IAC5D,QAAQ,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,CAAC,kBAAkB,EAAE,aAAa,EAAE,CAAC,EAAE;IACrG,IAAI;IACJ;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"plugin.js","sources":["esm/index.js","esm/web.js"],"sourcesContent":["import { registerPlugin } from '@capacitor/core';\nconst platformPlugin = registerPlugin('mDNS', {\n web: () => import('./web').then((m) => new m.mDNSWeb()),\n electron: () => {\n var _a, _b;\n const plugin = (_b = (_a = window.CapacitorCustomPlatform) === null || _a === void 0 ? void 0 : _a.plugins) === null || _b === void 0 ? void 0 : _b.mDNS;\n if (!plugin)\n throw new Error('mDNS Electron plugin is not registered; run npx cap-electron sync in the app');\n return Promise.resolve(plugin);\n },\n});\nconst mDNS = new Proxy(platformPlugin, {\n get(target, property, receiver) {\n if (property !== 'discover')\n return Reflect.get(target, property, receiver);\n return (options) => {\n const timeout = options === null || options === void 0 ? void 0 : options.timeout;\n // Native JSON bridges turn NaN/Infinity into null, losing the invalid input.\n if (timeout != null && (typeof timeout !== 'number' || !Number.isFinite(timeout))) {\n return Promise.resolve({ error: true, errorMessage: 'Invalid timeout', servicesFound: 0, services: [] });\n }\n return target.discover(options);\n };\n },\n});\nexport * from './definitions';\nexport { mDNS };\n//# sourceMappingURL=index.js.map","// src/web.ts\nimport { WebPlugin } from '@capacitor/core';\n/**\n * Web implementation of the mDNS plugin.\n *\n * This class behaves as a thin proxy:\n * - In Electron (when a preload exposes window.mDNS/window.mdns), calls are forwarded over IPC.\n * - In a regular browser, mDNS is not available; methods resolve with well-shaped stub values\n * and log a console message with the [WEB_NOT_SUPPORTED] tag.\n */\nexport class mDNSWeb extends WebPlugin {\n constructor() {\n super(...arguments);\n this.unsupportedMessage = 'mDNS is not supported in this browser runtime';\n }\n /** Electron preload bridge (if present). */\n get electronApi() {\n if (typeof window === 'undefined')\n return undefined;\n return window.mDNS || window.mdns;\n }\n async getPluginPlatform() {\n const api = this.electronApi;\n if (api === null || api === void 0 ? void 0 : api.getPluginPlatform)\n return api.getPluginPlatform();\n return { platform: 'web' };\n }\n async startBroadcast(options) {\n const api = this.electronApi;\n if (api === null || api === void 0 ? void 0 : api.startBroadcast)\n return api.startBroadcast(options);\n console.log('[WEB_NOT_SUPPORTED] startBroadcast', options);\n return { publishing: false, name: '', error: true, errorMessage: this.unsupportedMessage };\n }\n async stopBroadcast() {\n const api = this.electronApi;\n if (api === null || api === void 0 ? void 0 : api.stopBroadcast)\n return api.stopBroadcast();\n console.log('[WEB_NOT_SUPPORTED] stopBroadcast');\n return { publishing: false, error: false, errorMessage: null };\n }\n async discover(options = {}) {\n const api = this.electronApi;\n if (api === null || api === void 0 ? void 0 : api.discover)\n return api.discover(options);\n console.log('[WEB_NOT_SUPPORTED] discover', options);\n return { services: [], error: true, errorMessage: this.unsupportedMessage, servicesFound: 0 };\n }\n async watchServices(options) {\n var _a;\n if ((_a = this.electronApi) === null || _a === void 0 ? void 0 : _a.watchServices)\n return this.electronApi.watchServices(options);\n return { error: true, errorMessage: this.unsupportedMessage, watchersStarted: 0 };\n }\n async stopWatching() {\n var _a;\n if ((_a = this.electronApi) === null || _a === void 0 ? void 0 : _a.stopWatching)\n return this.electronApi.stopWatching();\n return { watching: false, error: false, errorMessage: null };\n }\n async addListener(eventName, handler) {\n var _a;\n if ((_a = this.electronApi) === null || _a === void 0 ? void 0 : _a.addListener)\n return this.electronApi.addListener(eventName, handler);\n return super.addListener(eventName, handler);\n }\n async removeAllListeners() {\n var _a, _b;\n await ((_b = (_a = this.electronApi) === null || _a === void 0 ? void 0 : _a.removeAllListeners) === null || _b === void 0 ? void 0 : _b.call(_a));\n await super.removeAllListeners();\n }\n}\n//# sourceMappingURL=web.js.map"],"names":["registerPlugin","WebPlugin"],"mappings":";;;IACA,MAAM,cAAc,GAAGA,mBAAc,CAAC,MAAM,EAAE;IAC9C,IAAI,GAAG,EAAE,MAAM,mDAAe,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,OAAO,EAAE,CAAC;IAC3D,IAAI,QAAQ,EAAE,MAAM;IACpB,QAAQ,IAAI,EAAE,EAAE,EAAE;IAClB,QAAQ,MAAM,MAAM,GAAG,CAAC,EAAE,GAAG,CAAC,EAAE,GAAG,MAAM,CAAC,uBAAuB,MAAM,IAAI,IAAI,EAAE,KAAK,MAAM,GAAG,MAAM,GAAG,EAAE,CAAC,OAAO,MAAM,IAAI,IAAI,EAAE,KAAK,MAAM,GAAG,MAAM,GAAG,EAAE,CAAC,IAAI;IAChK,QAAQ,IAAI,CAAC,MAAM;IACnB,YAAY,MAAM,IAAI,KAAK,CAAC,8EAA8E,CAAC;IAC3G,QAAQ,OAAO,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC;IACtC,IAAI,CAAC;IACL,CAAC,CAAC;AACG,UAAC,IAAI,GAAG,IAAI,KAAK,CAAC,cAAc,EAAE;IACvC,IAAI,GAAG,CAAC,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE;IACpC,QAAQ,IAAI,QAAQ,KAAK,UAAU;IACnC,YAAY,OAAO,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,QAAQ,EAAE,QAAQ,CAAC;IAC1D,QAAQ,OAAO,CAAC,OAAO,KAAK;IAC5B,YAAY,MAAM,OAAO,GAAG,OAAO,KAAK,IAAI,IAAI,OAAO,KAAK,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,OAAO;IAC7F;IACA,YAAY,IAAI,OAAO,IAAI,IAAI,KAAK,OAAO,OAAO,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,EAAE;IAC/F,gBAAgB,OAAO,OAAO,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,YAAY,EAAE,iBAAiB,EAAE,aAAa,EAAE,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;IACxH,YAAY;IACZ,YAAY,OAAO,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC;IAC3C,QAAQ,CAAC;IACT,IAAI,CAAC;IACL,CAAC;;ICxBD;IAEA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACO,MAAM,OAAO,SAASC,cAAS,CAAC;IACvC,IAAI,WAAW,GAAG;IAClB,QAAQ,KAAK,CAAC,GAAG,SAAS,CAAC;IAC3B,QAAQ,IAAI,CAAC,kBAAkB,GAAG,+CAA+C;IACjF,IAAI;IACJ;IACA,IAAI,IAAI,WAAW,GAAG;IACtB,QAAQ,IAAI,OAAO,MAAM,KAAK,WAAW;IACzC,YAAY,OAAO,SAAS;IAC5B,QAAQ,OAAO,MAAM,CAAC,IAAI,IAAI,MAAM,CAAC,IAAI;IACzC,IAAI;IACJ,IAAI,MAAM,iBAAiB,GAAG;IAC9B,QAAQ,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW;IACpC,QAAQ,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,MAAM,GAAG,MAAM,GAAG,GAAG,CAAC,iBAAiB;IAC3E,YAAY,OAAO,GAAG,CAAC,iBAAiB,EAAE;IAC1C,QAAQ,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE;IAClC,IAAI;IACJ,IAAI,MAAM,cAAc,CAAC,OAAO,EAAE;IAClC,QAAQ,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW;IACpC,QAAQ,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,MAAM,GAAG,MAAM,GAAG,GAAG,CAAC,cAAc;IACxE,YAAY,OAAO,GAAG,CAAC,cAAc,CAAC,OAAO,CAAC;IAC9C,QAAQ,OAAO,CAAC,GAAG,CAAC,oCAAoC,EAAE,OAAO,CAAC;IAClE,QAAQ,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,CAAC,kBAAkB,EAAE;IAClG,IAAI;IACJ,IAAI,MAAM,aAAa,GAAG;IAC1B,QAAQ,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW;IACpC,QAAQ,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,MAAM,GAAG,MAAM,GAAG,GAAG,CAAC,aAAa;IACvE,YAAY,OAAO,GAAG,CAAC,aAAa,EAAE;IACtC,QAAQ,OAAO,CAAC,GAAG,CAAC,mCAAmC,CAAC;IACxD,QAAQ,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE;IACtE,IAAI;IACJ,IAAI,MAAM,QAAQ,CAAC,OAAO,GAAG,EAAE,EAAE;IACjC,QAAQ,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW;IACpC,QAAQ,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,MAAM,GAAG,MAAM,GAAG,GAAG,CAAC,QAAQ;IAClE,YAAY,OAAO,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC;IACxC,QAAQ,OAAO,CAAC,GAAG,CAAC,8BAA8B,EAAE,OAAO,CAAC;IAC5D,QAAQ,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,CAAC,kBAAkB,EAAE,aAAa,EAAE,CAAC,EAAE;IACrG,IAAI;IACJ,IAAI,MAAM,aAAa,CAAC,OAAO,EAAE;IACjC,QAAQ,IAAI,EAAE;IACd,QAAQ,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC,WAAW,MAAM,IAAI,IAAI,EAAE,KAAK,MAAM,GAAG,MAAM,GAAG,EAAE,CAAC,aAAa;IACzF,YAAY,OAAO,IAAI,CAAC,WAAW,CAAC,aAAa,CAAC,OAAO,CAAC;IAC1D,QAAQ,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,CAAC,kBAAkB,EAAE,eAAe,EAAE,CAAC,EAAE;IACzF,IAAI;IACJ,IAAI,MAAM,YAAY,GAAG;IACzB,QAAQ,IAAI,EAAE;IACd,QAAQ,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC,WAAW,MAAM,IAAI,IAAI,EAAE,KAAK,MAAM,GAAG,MAAM,GAAG,EAAE,CAAC,YAAY;IACxF,YAAY,OAAO,IAAI,CAAC,WAAW,CAAC,YAAY,EAAE;IAClD,QAAQ,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE;IACpE,IAAI;IACJ,IAAI,MAAM,WAAW,CAAC,SAAS,EAAE,OAAO,EAAE;IAC1C,QAAQ,IAAI,EAAE;IACd,QAAQ,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC,WAAW,MAAM,IAAI,IAAI,EAAE,KAAK,MAAM,GAAG,MAAM,GAAG,EAAE,CAAC,WAAW;IACvF,YAAY,OAAO,IAAI,CAAC,WAAW,CAAC,WAAW,CAAC,SAAS,EAAE,OAAO,CAAC;IACnE,QAAQ,OAAO,KAAK,CAAC,WAAW,CAAC,SAAS,EAAE,OAAO,CAAC;IACpD,IAAI;IACJ,IAAI,MAAM,kBAAkB,GAAG;IAC/B,QAAQ,IAAI,EAAE,EAAE,EAAE;IAClB,QAAQ,OAAO,CAAC,EAAE,GAAG,CAAC,EAAE,GAAG,IAAI,CAAC,WAAW,MAAM,IAAI,IAAI,EAAE,KAAK,MAAM,GAAG,MAAM,GAAG,EAAE,CAAC,kBAAkB,MAAM,IAAI,IAAI,EAAE,KAAK,MAAM,GAAG,MAAM,GAAG,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC1J,QAAQ,MAAM,KAAK,CAAC,kBAAkB,EAAE;IACxC,IAAI;IACJ;;;;;;;;;;;;;;;"}
package/docs/electron.md CHANGED
@@ -20,6 +20,10 @@ The Electron runtime generator reads plugin metadata from:
20
20
  import { pluginSettings } from '@devioarts/capacitor-mdns/electron/settings';
21
21
  ```
22
22
 
23
+ After installing or updating the plugin, run `npx cap-electron sync` in the application. If the
24
+ generated runtime has no `mDNS` plugin, the root API rejects with an error identifying this step.
25
+ This is a runtime setup error, before a platform implementation can return an operation result.
26
+
23
27
  The Electron main-process plugin class is exported from:
24
28
 
25
29
  ```ts
@@ -28,22 +32,33 @@ import { mDNS } from '@devioarts/capacitor-mdns/electron';
28
32
 
29
33
  ## Manual bridge
30
34
 
35
+ Continuous discovery uses the same `watchServices`, `stopWatching` and `addListener` API as native
36
+ platforms. After updating the plugin, run `npx cap-electron sync` so the generated metadata includes
37
+ the new methods and the `serviceFound`, `serviceLost`, `watchError` events.
38
+
31
39
  The older manual bridge remains available for apps that do not use
32
40
  `devioarts/capacitor-electron`.
33
41
 
34
- Install the runtime Bonjour dependency in the Electron app:
42
+ The Electron runtime needs `bonjour-service`. It is declared as an optional peer dependency
43
+ (only Electron apps need it), so install it in the Electron app:
35
44
 
36
45
  ```shell
37
- npm i bonjour-service@1.4.0
46
+ npm i bonjour-service@~1.4.0
38
47
  ```
39
48
 
49
+ The supported range is `~1.4.0` because probe cleanup uses Bonjour 1.4 service behavior. Before widening
50
+ it, run the real-registry regressions for conflicts, pending announcements and goodbye packets.
51
+
40
52
  ### Main process
41
53
 
42
54
  ```ts
43
55
  import { app } from 'electron';
44
56
  import { mDNS } from '@devioarts/capacitor-mdns/electron';
45
57
 
46
- const mdns = new mDNS();
58
+ const mdns = new mDNS(undefined, {
59
+ // Only needed for an exact development server or a custom application origin:
60
+ // trustedOrigins: ['http://localhost:5173'],
61
+ });
47
62
 
48
63
  app.whenReady().then(() => {
49
64
  mdns.init();
@@ -63,3 +78,14 @@ const { createMDNSAPI } = require('@devioarts/capacitor-mdns/electron/mdns-bridg
63
78
  contextBridge.exposeInMainWorld('mDNS', createMDNSAPI({ ipcRenderer }));
64
79
  contextBridge.exposeInMainWorld('mdns', createMDNSAPI({ ipcRenderer }));
65
80
  ```
81
+
82
+ ### IPC trust
83
+
84
+ Manual handlers accept calls only from a trusted top-level frame. By default these are
85
+ `capacitor-electron://localhost` and `file:` documents inside `app.getAppPath()`.
86
+ Unpackaged apps also accept the Capacitor Electron default dev origin `http://localhost:5173`;
87
+ that default dev origin is disabled in packaged apps.
88
+ For a custom protocol or development server, configure its exact origin with `trustedOrigins`.
89
+ Third-party pages, child frames and other origins are rejected. Event delivery uses the same
90
+ URL allowlist, so windows displaying remote pages do not receive service data. The generated
91
+ Capacitor Electron route additionally applies its runtime's sender validation.
@@ -45,8 +45,14 @@ Add the local network permissions and every Bonjour service type your app uses t
45
45
  <key>NSBonjourServices</key>
46
46
  <array>
47
47
  <string>_http._tcp</string>
48
+ <string>_airplay._tcp</string>
49
+ <string>_googlecast._tcp</string>
48
50
  </array>
49
51
  ```
50
52
 
51
53
  For a custom service such as `_capmdnse2e._tcp.`, add `_capmdnse2e._tcp` to
52
54
  `NSBonjourServices`.
55
+
56
+ For continuous watching, include every type passed to `watchServices`. For example, watching
57
+ `['_http._tcp.', '_airplay._tcp.', '_googlecast._tcp.']` requires all three entries shown above. A denied
58
+ Local Network permission is reported through `watchError` and stops the watch group.