diff --git a/README.md b/README.md index 69276d7..031833f 100644 --- a/README.md +++ b/README.md @@ -91,6 +91,11 @@ const colors = await messenger.sendRequest(availableColorsType, HOST_EXTENSION, // Send a notification to the host extension messenger.sendNotification(colorSelectType, HOST_EXTENSION, 'a85b20'); + +// Shorthand for the (most common) case of targeting the host extension — +// no need to pass HOST_EXTENSION explicitly +const sameColors = await messenger.sendExtensionRequest(availableColorsType, ''); +messenger.sendExtensionNotification(colorSelectType, 'a85b20'); ``` > **Note:** `messenger.start()` must be called before any messages can be received. Forgetting it causes all incoming messages to be silently dropped. diff --git a/examples/calico-colors/package.json b/examples/calico-colors/package.json index 7888f4f..2855b87 100644 --- a/examples/calico-colors/package.json +++ b/examples/calico-colors/package.json @@ -75,8 +75,8 @@ "watch": "tsc -w -p ./" }, "dependencies": { - "vscode-messenger": "^0.6", - "vscode-messenger-webview": "^0.6" + "vscode-messenger": "^0.7", + "vscode-messenger-webview": "^0.7" }, "devDependencies": { "browserify": "^17.0.0", diff --git a/package-lock.json b/package-lock.json index a16b501..f5e22f1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -33,8 +33,8 @@ "version": "0.0.1", "license": "MIT", "dependencies": { - "vscode-messenger": "^0.6", - "vscode-messenger-webview": "^0.6" + "vscode-messenger": "^0.7", + "vscode-messenger-webview": "^0.7" }, "devDependencies": { "@types/vscode": "^1.53.0", @@ -44,30 +44,6 @@ "vscode": "^1.74.0" } }, - "examples/calico-colors/node_modules/vscode-messenger": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/vscode-messenger/-/vscode-messenger-0.6.1.tgz", - "integrity": "sha512-WBfvs6UsoQN3+q9Z5h03Ht/xPriu3ItO9BgZgr9invV0slSexLsM6PFa4ixpXELkvnNlh7mASP/VAf7DvcTeiw==", - "license": "MIT", - "dependencies": { - "vscode-messenger-common": "^0.6" - } - }, - "examples/calico-colors/node_modules/vscode-messenger-common": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/vscode-messenger-common/-/vscode-messenger-common-0.6.1.tgz", - "integrity": "sha512-QqF+Rz44n3KRMHh4mk5WXSLJHHl+aCTkzZZ0hGl2tnzPp+F1rNv8K6K3fhwJhjkoqKhko3WgEzR88JgNUCIsCw==", - "license": "MIT" - }, - "examples/calico-colors/node_modules/vscode-messenger-webview": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/vscode-messenger-webview/-/vscode-messenger-webview-0.6.1.tgz", - "integrity": "sha512-ynuyazyEjURr1gsNbL5EGmMcHph6Lp5vHzWj9SvVu+6KLbYD6u/HaXezhy0pNVefUvNuBDLqjod9SHlu01t94Q==", - "license": "MIT", - "dependencies": { - "vscode-messenger-common": "^0.6" - } - }, "node_modules/@babel/code-frame": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz", @@ -1322,29 +1298,43 @@ "license": "MIT" }, "node_modules/@humanfs/core": { - "version": "0.19.1", - "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", - "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.2.tgz", + "integrity": "sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==", "dev": true, "license": "Apache-2.0", + "dependencies": { + "@humanfs/types": "^0.15.0" + }, "engines": { "node": ">=18.18.0" } }, "node_modules/@humanfs/node": { - "version": "0.16.7", - "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.7.tgz", - "integrity": "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==", + "version": "0.16.8", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.8.tgz", + "integrity": "sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@humanfs/core": "^0.19.1", + "@humanfs/core": "^0.19.2", + "@humanfs/types": "^0.15.0", "@humanwhocodes/retry": "^0.4.0" }, "engines": { "node": ">=18.18.0" } }, + "node_modules/@humanfs/types": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/@humanfs/types/-/types-0.15.0.tgz", + "integrity": "sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, "node_modules/@humanwhocodes/module-importer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", @@ -3106,9 +3096,9 @@ "license": "MIT" }, "node_modules/baseline-browser-mapping": { - "version": "2.10.38", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.38.tgz", - "integrity": "sha512-31/02mVB4yuQU6adKk5SlY6m+mxDwUq5KZkyYgnLrrKl7TEm1+3PyDtDBz2kOv/wxZz41GHsvV1A/u6RmiyBvw==", + "version": "2.11.21", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.11.21.tgz", + "integrity": "sha512-uh8vpY/1/YyFkunIDFH/12p7/7VdPKA1hejMVEbdkEaWnUz0Hesvx5EbiU6XxjyHZIOju+ZMbQJkRh+es3/spQ==", "dev": true, "license": "Apache-2.0", "bin": { @@ -3350,9 +3340,9 @@ "license": "MIT" }, "node_modules/browserslist": { - "version": "4.28.2", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.2.tgz", - "integrity": "sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==", + "version": "4.28.8", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.8.tgz", + "integrity": "sha512-V2NpofLblG64mfOtSgDhOJESZEGogzDMBv/q+W6oc4LXWP/q75eOXoOaaOu1EOadB9U4Bwx/e0yzbvwKH8zalA==", "dev": true, "funding": [ { @@ -3370,11 +3360,11 @@ ], "license": "MIT", "dependencies": { - "baseline-browser-mapping": "^2.10.12", - "caniuse-lite": "^1.0.30001782", - "electron-to-chromium": "^1.5.328", - "node-releases": "^2.0.36", - "update-browserslist-db": "^1.2.3" + "baseline-browser-mapping": "^2.11.12", + "caniuse-lite": "^1.0.30001809", + "electron-to-chromium": "^1.5.402", + "node-releases": "^2.0.53", + "update-browserslist-db": "^1.3.0" }, "bin": { "browserslist": "cli.js" @@ -3520,9 +3510,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001799", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001799.tgz", - "integrity": "sha512-hG1bReV+OUU+MOqK4t/ZWI0tZOyz3rqS9XuhOUz1cIcbwBKjOyJEJuw9ER5JuNyqxNk8u/JUVbGibBOL1yrjFw==", + "version": "1.0.30001810", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001810.tgz", + "integrity": "sha512-TITQPUkaz+aVk5GL6NhOdwk1aEaNTSDPsGFWrTuhKGtjTF70jL/Oht2W4c6rXUe5fu7Ie19VIahAXHIIiWWNeg==", "dev": true, "funding": [ { @@ -4274,9 +4264,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.376", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.376.tgz", - "integrity": "sha512-cUVA7/RvbFTEuw/i3obUwDTRIXojaxkResf+ibByPFxjc6XK3VNtcQXV0NSbAlJ0FMjcJGgftVVB4Qo184EXvA==", + "version": "1.5.422", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.422.tgz", + "integrity": "sha512-UvA/32XqrLDdZSn7Jllo1AYNcWji/G0d5M0GTViE7KoGBiMunw3a34Sb2KO4ZZyrSEhqsxFoVhWWJshdyfKqJA==", "dev": true, "license": "ISC" }, @@ -7098,9 +7088,9 @@ "license": "MIT" }, "node_modules/node-releases": { - "version": "2.0.48", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.48.tgz", - "integrity": "sha512-1uz8041X6LoI6ZSdZacM9lVY28vuzDlSKitnpbSNK0RfKoIJkX29NBPVEFXhnuSuEOA9Ww0xnPJ+ILWbGAv8DA==", + "version": "2.0.54", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.54.tgz", + "integrity": "sha512-YHs7BmmcsdAI5Ozuf8JZo6PT0mv2GIWC9vMfvUC3dp65M8hn7Ux8CPL+2oBI7juNuj9d0ndhTcznq2ODBps9cQ==", "dev": true, "license": "MIT", "engines": { @@ -7529,9 +7519,9 @@ } }, "node_modules/postcss": { - "version": "8.5.26", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.26.tgz", - "integrity": "sha512-u82N74LFzG8ca+dD8puPnplTXoGH4fTPpVGuIbt36G3qvNlkvfD0lEAZSxaly3KX8TS/L1A1gsCEmvKmBcVbkQ==", + "version": "8.5.28", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.28.tgz", + "integrity": "sha512-RRuzqDtt5Y9h3quz5hWhK+TPnsmVs6WwSU6LkJMeY4HstUEDuYTG8UJSdawMRzmzAtV+KEoG8N3Qg2qLy5vM/A==", "dev": true, "funding": [ { @@ -7549,7 +7539,7 @@ ], "license": "MIT", "dependencies": { - "nanoid": "^3.3.17", + "nanoid": "^3.3.18", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" }, @@ -7673,13 +7663,14 @@ } }, "node_modules/qs": { - "version": "6.15.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.2.tgz", - "integrity": "sha512-Rzq0KEyX/w/tEybncDgdkZrJgVUsUMk3xjh3t5bv3S1HTAtg+uOYt72+ZfwiQwKdysThkTBdL/rTi6HDmX9Ddw==", + "version": "6.16.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.16.0.tgz", + "integrity": "sha512-h6fhOIaRrID2CbEY2fqs+7t+UXZo+MLAnU5gRIq85uFtdiUPCdsApMlHhXogKVM4HM2DVbIjGNTTYH2OcmP1vA==", "dev": true, "license": "BSD-3-Clause", "dependencies": { - "side-channel": "^1.1.0" + "es-define-property": "^1.0.1", + "side-channel": "^1.1.1" }, "engines": { "node": ">=0.6" @@ -8173,15 +8164,15 @@ } }, "node_modules/side-channel": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", - "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.1.tgz", + "integrity": "sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==", "dev": true, "license": "MIT", "dependencies": { "es-errors": "^1.3.0", - "object-inspect": "^1.13.3", - "side-channel-list": "^1.0.0", + "object-inspect": "^1.13.4", + "side-channel-list": "^1.0.1", "side-channel-map": "^1.0.1", "side-channel-weakmap": "^1.0.2" }, @@ -8193,14 +8184,14 @@ } }, "node_modules/side-channel-list": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", - "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz", + "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==", "dev": true, "license": "MIT", "dependencies": { "es-errors": "^1.3.0", - "object-inspect": "^1.13.3" + "object-inspect": "^1.13.4" }, "engines": { "node": ">= 0.4" @@ -8991,9 +8982,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", - "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.3.2.tgz", + "integrity": "sha512-UQ+MSxlhRm1bzjhU+DcuXfjFO1FzNtqhK5+9Yvlp90ItDLk5vT932A0rFu619nf7RVS+Y/VeaUW1jaRDqZ8VJw==", "dev": true, "funding": [ { @@ -9621,30 +9612,15 @@ "dev": true, "license": "MIT" }, - "packages/vscode-messenger-devtools/node_modules/vscode-messenger-common": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/vscode-messenger-common/-/vscode-messenger-common-0.6.1.tgz", - "integrity": "sha512-QqF+Rz44n3KRMHh4mk5WXSLJHHl+aCTkzZZ0hGl2tnzPp+F1rNv8K6K3fhwJhjkoqKhko3WgEzR88JgNUCIsCw==", - "license": "MIT" - }, - "packages/vscode-messenger-devtools/node_modules/vscode-messenger-webview": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/vscode-messenger-webview/-/vscode-messenger-webview-0.6.1.tgz", - "integrity": "sha512-ynuyazyEjURr1gsNbL5EGmMcHph6Lp5vHzWj9SvVu+6KLbYD6u/HaXezhy0pNVefUvNuBDLqjod9SHlu01t94Q==", - "license": "MIT", - "dependencies": { - "vscode-messenger-common": "^0.6" - } - }, "packages/vscode-messenger-devtools/webview-ui": { "name": "devtools-ui", - "version": "0.6.0", + "version": "0.7.0", "dependencies": { "@tanstack/react-table": "~8.21.3", "baukasten-ui": "0.3.0-next.027be66", "react": "~19.2", "react-dom": "~19.2", - "vscode-messenger-webview": "~0.6.0", + "vscode-messenger-webview": "~0.7.0", "zustand": "~3.7.2" }, "devDependencies": { diff --git a/packages/vscode-messenger-devtools/webview-ui/package.json b/packages/vscode-messenger-devtools/webview-ui/package.json index 1dcd648..98bfe5e 100644 --- a/packages/vscode-messenger-devtools/webview-ui/package.json +++ b/packages/vscode-messenger-devtools/webview-ui/package.json @@ -1,6 +1,6 @@ { "name": "devtools-ui", - "version": "0.6.0", + "version": "0.7.0", "private": true, "scripts": { "start": "vite", @@ -15,7 +15,7 @@ "baukasten-ui": "0.3.0-next.027be66", "react": "~19.2", "react-dom": "~19.2", - "vscode-messenger-webview": "~0.6.0", + "vscode-messenger-webview": "~0.7.0", "zustand": "~3.7.2" }, "devDependencies": { diff --git a/packages/vscode-messenger-webview/src/messenger.ts b/packages/vscode-messenger-webview/src/messenger.ts index cc7084a..a0e1cb3 100644 --- a/packages/vscode-messenger-webview/src/messenger.ts +++ b/packages/vscode-messenger-webview/src/messenger.ts @@ -13,6 +13,7 @@ import type { import { CancellationTokenImpl, Deferred, + HOST_EXTENSION, createCancelRequestMessage, isCancelRequestNotification, isMessage, @@ -356,6 +357,33 @@ export class Messenger implements MessengerAPI { return pending.result; } + /** + * Send a request message to the host extension and wait for a response. + * + * Shorthand for `sendRequest(type, HOST_EXTENSION, params, cancelable)`, since sending a + * request to the host extension is the most common case on the webview side. + * + * @template P The type of the request parameters + * @template R The type of the response data + * @param type The request type definition containing the method name + * @param params Optional parameters to send with the request + * @param cancelable Optional cancellation token to cancel the request + * @returns A Promise that resolves with the response data or rejects if the request fails + * + * @see {@link sendRequest} - Use this instead when the receiver is not the host extension + * + * @example + * ```typescript + * const GetUserRequest: RequestType<{ userId: string }, { name: string }> = { method: 'getUser' }; + * + * // Equivalent to messenger.sendRequest(GetUserRequest, HOST_EXTENSION, { userId: '123' }) + * const user = await messenger.sendExtensionRequest(GetUserRequest, { userId: '123' }); + * ``` + */ + sendExtensionRequest(type: RequestType, params?: P, cancelable?: CancellationToken): Promise { + return this.sendRequest(type, HOST_EXTENSION, params, cancelable); + } + /** * Send a notification message to another participant without expecting a response. * @@ -410,6 +438,30 @@ export class Messenger implements MessengerAPI { this.vscode.postMessage(message); } + /** + * Send a notification message to the host extension without expecting a response. + * + * Shorthand for `sendNotification(type, HOST_EXTENSION, params)`, since sending a + * notification to the host extension is the most common case on the webview side. + * + * @template P The type of the notification parameters + * @param type The notification type definition containing the method name + * @param params Optional parameters to send with the notification + * + * @see {@link sendNotification} - Use this instead when the receiver is not the host extension + * + * @example + * ```typescript + * const UserLoggedInNotification: NotificationType<{ userId: string }> = { method: 'userLoggedIn' }; + * + * // Equivalent to messenger.sendNotification(UserLoggedInNotification, HOST_EXTENSION, { userId: '123' }) + * messenger.sendExtensionNotification(UserLoggedInNotification, { userId: '123' }); + * ``` + */ + sendExtensionNotification

(type: NotificationType

, params?: P): void { + this.sendNotification(type, HOST_EXTENSION, params); + } + private nextMsgId = 0; protected createMsgId(): string { diff --git a/packages/vscode-messenger-webview/tests/messenger-webview.test.ts b/packages/vscode-messenger-webview/tests/messenger-webview.test.ts index 891a59d..0e64f8e 100644 --- a/packages/vscode-messenger-webview/tests/messenger-webview.test.ts +++ b/packages/vscode-messenger-webview/tests/messenger-webview.test.ts @@ -118,6 +118,36 @@ describe('Webview Messenger', () => { ); }); + test('Send extension request', async () => { + const messenger = new Messenger(vsCodeApi); + messenger.start(); + + const response = await messenger.sendExtensionRequest(stringRequest, 'ping'); + + expect(vsCodeApi.messages[0]).toMatchObject( + { + method: 'stringRequest', + receiver: HOST_EXTENSION, + params: 'ping' + } + ); + expect(response).toBe('result:ping'); + }); + + test('Send extension notification', () => { + new Messenger(vsCodeApi).sendExtensionNotification(stringNotification, 'ping'); + + const message = vsCodeApi.messages[0] as unknown as any; + delete message.id; + expect(message).toMatchObject( + { + method: 'stringNotification', + receiver: HOST_EXTENSION, + params: 'ping' + } + ); + }); + test('Handle request from an extension', async () => { const messenger = new Messenger(vsCodeApi); messenger.onRequest(stringRequest, (r: string) => {