@device-portal/react 0.0.21 → 0.0.22
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.
|
@@ -64,10 +64,13 @@ function getOrCreateEntry(key, room, peerId, options) {
|
|
|
64
64
|
function scheduleDestroy(key) {
|
|
65
65
|
var entry = entries.get(key);
|
|
66
66
|
if (!entry || entry.destroyTimer !== null) return;
|
|
67
|
+
// setTimeout(0) so React Strict Mode's synchronous unmount/remount
|
|
68
|
+
// reclaims the entry before it's destroyed, while real unmounts
|
|
69
|
+
// (navigation, conditional render) clean up on the next microtask.
|
|
67
70
|
entry.destroyTimer = setTimeout(function () {
|
|
68
71
|
entry.consumer.destroy();
|
|
69
72
|
entries["delete"](key);
|
|
70
|
-
},
|
|
73
|
+
}, 0);
|
|
71
74
|
}
|
|
72
75
|
/**
|
|
73
76
|
* A React hook that joins a Device Portal room and receives values from the
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useDevicePortalConsumer.js","sources":["../../src/consumer/useDevicePortalConsumer.ts"],"sourcesContent":["import {\n\tClient,\n\tgeneratePeerId,\n\ttype BrowserDirectOption,\n\ttype PeerId,\n} from '@device-portal/client'\nimport { use, useCallback, useEffect, useRef, useState } from 'react'\n\n/**\n * Configuration options for the Device Portal Consumer.\n */\nexport type DevicePortalConsumerOptions = {\n\t/** URL of the signaling server, or null to disable. */\n\twebSocketSignalingServer?: string | null\n\t/** Browser direct signaling options. */\n\tbrowserDirect?: BrowserDirectOption\n\t/** Whether to automatically send the last 'send()' value back to the provider on reconnect. Default: false. */\n\tsendLastMessageOnReconnect?: boolean\n}\n\n// ---------------------------------------------------------------------------\n// Module-level cache for Consumer entries.\n//\n// Why module-level? The cache must survive React Suspense throws (which\n// discard in-progress render state) and React Strict Mode's synchronous\n// unmount/remount cycle. The entry is keyed by room + options, which is\n// stable across both scenarios.\n//\n// Cleanup uses a grace-period timeout so that Strict Mode's immediate\n// remount can reclaim the entry before it's destroyed.\n// ---------------------------------------------------------------------------\n\ntype ConsumerEntry = {\n\tconsumer: Client\n\tfirstValuePromise: Promise<string>\n\tlatestValue: string | undefined\n\tlastSentValue: string | undefined\n\tsetValue: ((value: string) => void) | null\n\tdestroyTimer: ReturnType<typeof setTimeout> | null\n\troom: string\n\toptionsSnapshot: string\n}\n\nconst entries = new Map<string, ConsumerEntry>()\n\nfunction optionsKey(options: DevicePortalConsumerOptions): string {\n\treturn `${options.webSocketSignalingServer ?? ''}\\0${options.browserDirect ?? ''}\\0${options.sendLastMessageOnReconnect ?? ''}`\n}\n\nfunction getOrCreateEntry(\n\tkey: string,\n\troom: string,\n\tpeerId: PeerId,\n\toptions: DevicePortalConsumerOptions,\n): ConsumerEntry {\n\tconst existing = entries.get(key)\n\tconst newOptionsKey = optionsKey(options)\n\n\tif (existing) {\n\t\t// Cancel any pending destruction\n\t\tif (existing.destroyTimer !== null) {\n\t\t\tclearTimeout(existing.destroyTimer)\n\t\t\texisting.destroyTimer = null\n\t\t}\n\t\t// Reuse if room + options unchanged\n\t\tif (existing.room === room && existing.optionsSnapshot === newOptionsKey) {\n\t\t\treturn existing\n\t\t}\n\t\t// Room/options changed – destroy old entry synchronously\n\t\texisting.consumer.destroy()\n\t\tentries.delete(key)\n\t}\n\n\t// Create a deferred promise for Suspense via use()\n\tlet resolveFirst!: (value: string) => void\n\tconst firstValuePromise = new Promise<string>((resolve) => {\n\t\tresolveFirst = resolve\n\t})\n\n\tconst sendLastMessageOnReconnect = options.sendLastMessageOnReconnect ?? false\n\n\tconst entry: ConsumerEntry = {\n\t\tconsumer: undefined!, // assigned below\n\t\tfirstValuePromise,\n\t\tlatestValue: undefined,\n\t\tlastSentValue: undefined,\n\t\tsetValue: null,\n\t\tdestroyTimer: null,\n\t\troom,\n\t\toptionsSnapshot: newOptionsKey,\n\t}\n\n\tentry.consumer = new Client(room, {\n\t\tonMessage: (value) => {\n\t\t\tentry.latestValue = value\n\t\t\tresolveFirst(value)\n\t\t\tentry.setValue?.(value)\n\t\t},\n\t\tonConnected: () => {\n\t\t\tif (sendLastMessageOnReconnect && entry.lastSentValue !== undefined) {\n\t\t\t\tentry.consumer.send(entry.lastSentValue)\n\t\t\t}\n\t\t},\n\t\twebSocketSignalingServer: options.webSocketSignalingServer,\n\t\tbrowserDirect: options.browserDirect,\n\t\tpeerId,\n\t})\n\n\tentries.set(key, entry)\n\treturn entry\n}\n\nfunction scheduleDestroy(key: string) {\n\tconst entry = entries.get(key)\n\tif (!entry || entry.destroyTimer !== null) return\n\n\tentry.destroyTimer = setTimeout(() => {\n\t\tentry.consumer.destroy()\n\t\tentries.delete(key)\n\t}, 5_000)\n}\n\n/**\n * A React hook that joins a Device Portal room and receives values from the\n * provider. **Suspends** the component until the first value is received —\n * wrap the consumer in a `<Suspense>` boundary.\n *\n * Requires React 19+. Uses `use()` for Suspense integration.\n *\n * Safe under React Strict Mode and concurrent features: the underlying\n * Consumer is cached with a grace-period cleanup so synchronous\n * unmount/remount cycles do not create duplicate connections.\n *\n * @param room - The unique room ID.\n * @param options - Consumer configuration options.\n */\nexport const useDevicePortalConsumer = (\n\troom: string,\n\toptions: DevicePortalConsumerOptions = {},\n): {\n\tvalue: string\n\tsendMessageToProvider: (message: string) => void\n} => {\n\t// Key by room + options rather than useId(), because useId() is not\n\t// stable across Suspense re-throws when sibling state updates cause\n\t// the component tree to re-mount.\n\tconst cacheKey = `${room}\\0${optionsKey(options)}`\n\tconst peerIdRef = useRef<PeerId>(generatePeerId())\n\n\tconst entry = getOrCreateEntry(cacheKey, room, peerIdRef.current, options)\n\n\t// Suspends until the first value arrives (React 19 use() API).\n\tconst firstValue = use(entry.firstValuePromise)\n\n\t// After the first value, track subsequent updates via useState.\n\tconst [value, setValue] = useState(() => entry.latestValue ?? firstValue)\n\n\t// Wire up the entry's setValue so the Consumer can push updates.\n\tentry.setValue = setValue\n\n\tuseEffect(() => {\n\t\tconst e = getOrCreateEntry(cacheKey, room, peerIdRef.current, options)\n\t\te.setValue = setValue\n\n\t\t// Sync in case a value arrived between render and effect commit.\n\t\tif (e.latestValue !== undefined) {\n\t\t\tsetValue(e.latestValue)\n\t\t}\n\n\t\treturn () => {\n\t\t\te.setValue = null\n\t\t\tscheduleDestroy(cacheKey)\n\t\t}\n\t}, [\n\t\tcacheKey,\n\t\troom,\n\t\toptions.webSocketSignalingServer,\n\t\toptions.browserDirect,\n\t\toptions.sendLastMessageOnReconnect,\n\t])\n\n\tconst sendMessageToProvider = useCallback(\n\t\t(message: string) => {\n\t\t\tentry.lastSentValue = message\n\t\t\tentry.consumer.send(message)\n\t\t},\n\t\t[entry],\n\t)\n\n\treturn { value, sendMessageToProvider }\n}\n"],"names":["entries","Map","optionsKey","options","_options$webSocketSig","_options$browserDirec","_options$sendLastMess","concat","webSocketSignalingServer","browserDirect","sendLastMessageOnReconnect","getOrCreateEntry","key","room","peerId","_options$sendLastMess2","existing","get","newOptionsKey","destroyTimer","clearTimeout","optionsSnapshot","consumer","destroy","resolveFirst","firstValuePromise","Promise","resolve","entry","undefined","latestValue","lastSentValue","setValue","Client","onMessage","value","_entry$setValue","call","onConnected","send","set","scheduleDestroy","setTimeout","useDevicePortalConsumer","arguments","length","cacheKey","peerIdRef","useRef","generatePeerId","current","firstValue","use","_useState","useState","_entry$latestValue","_useState2","_slicedToArray","useEffect","e","sendMessageToProvider","useCallback","message"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"useDevicePortalConsumer.js","sources":["../../src/consumer/useDevicePortalConsumer.ts"],"sourcesContent":["import {\n\tClient,\n\tgeneratePeerId,\n\ttype BrowserDirectOption,\n\ttype PeerId,\n} from '@device-portal/client'\nimport { use, useCallback, useEffect, useRef, useState } from 'react'\n\n/**\n * Configuration options for the Device Portal Consumer.\n */\nexport type DevicePortalConsumerOptions = {\n\t/** URL of the signaling server, or null to disable. */\n\twebSocketSignalingServer?: string | null\n\t/** Browser direct signaling options. */\n\tbrowserDirect?: BrowserDirectOption\n\t/** Whether to automatically send the last 'send()' value back to the provider on reconnect. Default: false. */\n\tsendLastMessageOnReconnect?: boolean\n}\n\n// ---------------------------------------------------------------------------\n// Module-level cache for Consumer entries.\n//\n// Why module-level? The cache must survive React Suspense throws (which\n// discard in-progress render state) and React Strict Mode's synchronous\n// unmount/remount cycle. The entry is keyed by room + options, which is\n// stable across both scenarios.\n//\n// Cleanup uses a grace-period timeout so that Strict Mode's immediate\n// remount can reclaim the entry before it's destroyed.\n// ---------------------------------------------------------------------------\n\ntype ConsumerEntry = {\n\tconsumer: Client\n\tfirstValuePromise: Promise<string>\n\tlatestValue: string | undefined\n\tlastSentValue: string | undefined\n\tsetValue: ((value: string) => void) | null\n\tdestroyTimer: ReturnType<typeof setTimeout> | null\n\troom: string\n\toptionsSnapshot: string\n}\n\nconst entries = new Map<string, ConsumerEntry>()\n\nfunction optionsKey(options: DevicePortalConsumerOptions): string {\n\treturn `${options.webSocketSignalingServer ?? ''}\\0${options.browserDirect ?? ''}\\0${options.sendLastMessageOnReconnect ?? ''}`\n}\n\nfunction getOrCreateEntry(\n\tkey: string,\n\troom: string,\n\tpeerId: PeerId,\n\toptions: DevicePortalConsumerOptions,\n): ConsumerEntry {\n\tconst existing = entries.get(key)\n\tconst newOptionsKey = optionsKey(options)\n\n\tif (existing) {\n\t\t// Cancel any pending destruction\n\t\tif (existing.destroyTimer !== null) {\n\t\t\tclearTimeout(existing.destroyTimer)\n\t\t\texisting.destroyTimer = null\n\t\t}\n\t\t// Reuse if room + options unchanged\n\t\tif (existing.room === room && existing.optionsSnapshot === newOptionsKey) {\n\t\t\treturn existing\n\t\t}\n\t\t// Room/options changed – destroy old entry synchronously\n\t\texisting.consumer.destroy()\n\t\tentries.delete(key)\n\t}\n\n\t// Create a deferred promise for Suspense via use()\n\tlet resolveFirst!: (value: string) => void\n\tconst firstValuePromise = new Promise<string>((resolve) => {\n\t\tresolveFirst = resolve\n\t})\n\n\tconst sendLastMessageOnReconnect = options.sendLastMessageOnReconnect ?? false\n\n\tconst entry: ConsumerEntry = {\n\t\tconsumer: undefined!, // assigned below\n\t\tfirstValuePromise,\n\t\tlatestValue: undefined,\n\t\tlastSentValue: undefined,\n\t\tsetValue: null,\n\t\tdestroyTimer: null,\n\t\troom,\n\t\toptionsSnapshot: newOptionsKey,\n\t}\n\n\tentry.consumer = new Client(room, {\n\t\tonMessage: (value) => {\n\t\t\tentry.latestValue = value\n\t\t\tresolveFirst(value)\n\t\t\tentry.setValue?.(value)\n\t\t},\n\t\tonConnected: () => {\n\t\t\tif (sendLastMessageOnReconnect && entry.lastSentValue !== undefined) {\n\t\t\t\tentry.consumer.send(entry.lastSentValue)\n\t\t\t}\n\t\t},\n\t\twebSocketSignalingServer: options.webSocketSignalingServer,\n\t\tbrowserDirect: options.browserDirect,\n\t\tpeerId,\n\t})\n\n\tentries.set(key, entry)\n\treturn entry\n}\n\nfunction scheduleDestroy(key: string) {\n\tconst entry = entries.get(key)\n\tif (!entry || entry.destroyTimer !== null) return\n\n\t// setTimeout(0) so React Strict Mode's synchronous unmount/remount\n\t// reclaims the entry before it's destroyed, while real unmounts\n\t// (navigation, conditional render) clean up on the next microtask.\n\tentry.destroyTimer = setTimeout(() => {\n\t\tentry.consumer.destroy()\n\t\tentries.delete(key)\n\t}, 0)\n}\n\n/**\n * A React hook that joins a Device Portal room and receives values from the\n * provider. **Suspends** the component until the first value is received —\n * wrap the consumer in a `<Suspense>` boundary.\n *\n * Requires React 19+. Uses `use()` for Suspense integration.\n *\n * Safe under React Strict Mode and concurrent features: the underlying\n * Consumer is cached with a grace-period cleanup so synchronous\n * unmount/remount cycles do not create duplicate connections.\n *\n * @param room - The unique room ID.\n * @param options - Consumer configuration options.\n */\nexport const useDevicePortalConsumer = (\n\troom: string,\n\toptions: DevicePortalConsumerOptions = {},\n): {\n\tvalue: string\n\tsendMessageToProvider: (message: string) => void\n} => {\n\t// Key by room + options rather than useId(), because useId() is not\n\t// stable across Suspense re-throws when sibling state updates cause\n\t// the component tree to re-mount.\n\tconst cacheKey = `${room}\\0${optionsKey(options)}`\n\tconst peerIdRef = useRef<PeerId>(generatePeerId())\n\n\tconst entry = getOrCreateEntry(cacheKey, room, peerIdRef.current, options)\n\n\t// Suspends until the first value arrives (React 19 use() API).\n\tconst firstValue = use(entry.firstValuePromise)\n\n\t// After the first value, track subsequent updates via useState.\n\tconst [value, setValue] = useState(() => entry.latestValue ?? firstValue)\n\n\t// Wire up the entry's setValue so the Consumer can push updates.\n\tentry.setValue = setValue\n\n\tuseEffect(() => {\n\t\tconst e = getOrCreateEntry(cacheKey, room, peerIdRef.current, options)\n\t\te.setValue = setValue\n\n\t\t// Sync in case a value arrived between render and effect commit.\n\t\tif (e.latestValue !== undefined) {\n\t\t\tsetValue(e.latestValue)\n\t\t}\n\n\t\treturn () => {\n\t\t\te.setValue = null\n\t\t\tscheduleDestroy(cacheKey)\n\t\t}\n\t}, [\n\t\tcacheKey,\n\t\troom,\n\t\toptions.webSocketSignalingServer,\n\t\toptions.browserDirect,\n\t\toptions.sendLastMessageOnReconnect,\n\t])\n\n\tconst sendMessageToProvider = useCallback(\n\t\t(message: string) => {\n\t\t\tentry.lastSentValue = message\n\t\t\tentry.consumer.send(message)\n\t\t},\n\t\t[entry],\n\t)\n\n\treturn { value, sendMessageToProvider }\n}\n"],"names":["entries","Map","optionsKey","options","_options$webSocketSig","_options$browserDirec","_options$sendLastMess","concat","webSocketSignalingServer","browserDirect","sendLastMessageOnReconnect","getOrCreateEntry","key","room","peerId","_options$sendLastMess2","existing","get","newOptionsKey","destroyTimer","clearTimeout","optionsSnapshot","consumer","destroy","resolveFirst","firstValuePromise","Promise","resolve","entry","undefined","latestValue","lastSentValue","setValue","Client","onMessage","value","_entry$setValue","call","onConnected","send","set","scheduleDestroy","setTimeout","useDevicePortalConsumer","arguments","length","cacheKey","peerIdRef","useRef","generatePeerId","current","firstValue","use","_useState","useState","_entry$latestValue","_useState2","_slicedToArray","useEffect","e","sendMessageToProvider","useCallback","message"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@device-portal/react",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.22",
|
|
4
4
|
"description": "Simple WebRTC data channel for React.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"react": ">=19"
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@device-portal/client": "^0.0.
|
|
42
|
+
"@device-portal/client": "^0.0.22"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
45
|
"@babel/core": "^7.24.0",
|