-
Notifications
You must be signed in to change notification settings - Fork 23
Arc 412 extract and publish npm package #1575
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
…package' into ARC-412-Extract-and-publish-NPM-package
Let maintainers know that an action is required on their side
|
Maintainer action requestedAuthor requested libraries to be published. cc @CBenoit |
2307372 to
d400247
Compare
refactor(recording): publishing npm package fix(recording-player): use published shadow-player exports instead of internal paths
d400247 to
14a9bf4
Compare
|
@Skyzreal Are you looking for initial feedback on your draft PR? |
|
@CBenoit Yes, exactly, I'm taking some time this morning to review the changes and would really appreciate any initial feedback, especially since it’s my first time commiting in the devolutions-gateway repo |
| "private": true, | ||
| "version": "0.0.0", | ||
| "private": false, | ||
| "version": "1.0.0", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion: Let’s start with 0.1.0 (pre v1)
| "version": "1.0.0", | |
| "version": "0.1.0", |
| "main": "./dist/shadow-player.js", | ||
| "module": "./dist/shadow-player.js", | ||
| "main": "./dist/webm-stream-player.js", | ||
| "module": "./dist/webm-stream-player.js", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
question: Is it intended? I see this is the package.json from shadow-player 🤔
suggestion: Use shadow-player; or better: many packages are using a generic index name for the entry points.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for noticing! I cleaned it up so the package now uses the standard index
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR prepares two packages (@devolutions/shadow-player and @devolutions/multi-video-player) for publication to npm by changing them from private to public packages. The changes include adding proper peer dependencies, implementing a Gateway API client for fetching recording data, and adding cleanup functionality to the shadow player.
Key changes:
- Published shadow-player (v1.0.0) and multi-video-player (v1.0.0) as public npm packages
- Implemented
GatewayRecordingApiclient for Gateway recording operations - Added
disconnect()method to shadow-player for proper resource cleanup
Reviewed Changes
Copilot reviewed 11 out of 12 changed files in this pull request and generated 11 comments.
Show a summary per file
| File | Description |
|---|---|
| webapp/pnpm-lock.yaml | Added shadow-player as a workspace dependency for multi-video-player |
| webapp/packages/shadow-player/src/streamer.ts | Added disconnect method, session-not-found error type, and improved WebSocket lifecycle management |
| webapp/packages/shadow-player/package.json | Changed to public package v1.0.0 with updated entry points |
| webapp/packages/shadow-player/build.ps1 | Added PowerShell build script for package distribution |
| webapp/packages/multi-video-player/vite.config.ts | Externalized video.js and shadow-player dependencies |
| webapp/packages/multi-video-player/src/live-streamer.ts | New class for managing live recording streams with shadow-player |
| webapp/packages/multi-video-player/src/index.ts | Exported gateway-api and live-streamer modules |
| webapp/packages/multi-video-player/src/gateway-api.ts | New Gateway API client for recording operations |
| webapp/packages/multi-video-player/package.json | Changed to public package v1.0.0 with peer dependencies |
| webapp/packages/multi-video-player/build.ps1 | Added PowerShell build script for package distribution |
| webapp/apps/recording-player/src/streamers/webm.ts | Updated imports to use published package paths |
| .github/workflows/publish-libraries.yml | Added multi-video-player and shadow-player to npm publishing workflow |
Files not reviewed (1)
- webapp/pnpm-lock.yaml: Language not supported
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| } | ||
|
|
||
| public disconnect(): void { | ||
| this.isDisconnecting = true; |
Copilot
AI
Nov 19, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The isDisconnecting flag is set to true at the start of disconnect() but is never reset to false. If the shadow player component is reused after calling disconnect(), subsequent operations might behave incorrectly. Consider resetting this flag after cleanup is complete, or document that the component should not be reused after disconnect.
| "types": "./dist/shadow-player.d.ts", | ||
| "exports": { | ||
| ".": { | ||
| "import": "./dist/webm-stream-player.js", | ||
| "types": "./dist/shadow-player.d.ts" |
Copilot
AI
Nov 19, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The main and module fields point to webm-stream-player.js but the exports field also points to webm-stream-player.js, while the types field points to shadow-player.d.ts. This inconsistency in naming could cause issues. The main bundle filename appears to be webm-stream-player.js but the type definitions use a different basename (shadow-player). Consider ensuring these filenames are consistent or verify that the build process generates both correctly.
| "types": "./dist/shadow-player.d.ts", | |
| "exports": { | |
| ".": { | |
| "import": "./dist/webm-stream-player.js", | |
| "types": "./dist/shadow-player.d.ts" | |
| "types": "./dist/webm-stream-player.d.ts", | |
| "exports": { | |
| ".": { | |
| "import": "./dist/webm-stream-player.js", | |
| "types": "./dist/webm-stream-player.d.ts" |
| "vite-plugin-bundle-css": "^0.1.1" | ||
| }, | ||
| "peerDependencies": { | ||
| "@devolutions/shadow-player": "workspace:*", |
Copilot
AI
Nov 19, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The peer dependency for @devolutions/shadow-player is set to workspace:*, but this is not a valid version specifier for published packages. When this package is published to npm, workspace:* won't resolve correctly for consumers outside the workspace. This should be changed to a semantic version range like ^1.0.0 to match the published version of shadow-player.
| "@devolutions/shadow-player": "workspace:*", | |
| "@devolutions/shadow-player": "^1.0.0", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably needs to be addressed, but I’m not sure how we are supposed to deal with that with npm.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion: Refer to my suggestion about the "two package.json files" approach.
| if (reactiveSourceBuffer && mediaSource.readyState === 'open') { | ||
| try { | ||
| mediaSource.endOfStream(); | ||
| } catch (error) { |
Copilot
AI
Nov 19, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The error in the catch block is being silently swallowed without any logging or handling. Consider at least logging the error for debugging purposes, or add a comment explaining why it's safe to ignore this error.
| } catch (error) { | |
| } catch (error) { | |
| console.error('endOfStream error:', error); |
| } catch (error) { | ||
| } |
Copilot
AI
Nov 19, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The error in the catch block is being silently swallowed without any logging or handling. Consider at least logging the error for debugging purposes, or add a comment explaining why it's safe to ignore this error.
| } | ||
|
|
||
| const sessions = await response.json(); | ||
| const sessionExists = sessions.some((session: any) => session.id === this.sessionId); |
Copilot
AI
Nov 19, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using any type defeats the purpose of TypeScript's type safety. Consider defining a proper interface for the session object, e.g., interface Session { id: string; ... } and typing the sessions array appropriately.
| @@ -0,0 +1,19 @@ | |||
| #!/bin/env pwsh | |||
Copilot
AI
Nov 19, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The shebang line is incorrect. It should be #!/usr/bin/env pwsh instead of #!/bin/env pwsh to properly locate the pwsh interpreter using the env command.
| #!/bin/env pwsh | |
| #!/usr/bin/env pwsh |
| @@ -0,0 +1,19 @@ | |||
| #!/bin/env pwsh | |||
Copilot
AI
Nov 19, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The shebang line is incorrect. It should be #!/usr/bin/env pwsh instead of #!/bin/env pwsh to properly locate the pwsh interpreter using the env command.
| #!/bin/env pwsh | |
| #!/usr/bin/env pwsh |
| } catch (error) { | ||
| } |
Copilot
AI
Nov 19, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The error in the catch block is being silently swallowed without any logging or handling. Consider at least logging the error for debugging purposes, or add a comment explaining why it's safe to ignore this error.
|
|
||
| return sessionExists; | ||
| } catch (error) { | ||
|
|
Copilot
AI
Nov 19, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The error in the catch block is being silently swallowed without any logging or handling. Consider at least logging the error for debugging purposes so issues can be diagnosed if the session check fails unexpectedly.
| console.error('Error checking session activity:', error); |
|
Please follow this Git workflow: https://github.com/Devolutions/devolutions-gateway/blob/4304148f0979809d3941543d2083101abc293840/AGENTS.md#git-workflow |
| "peerDependencies": { | ||
| "@devolutions/shadow-player": "workspace:*", | ||
| "video.js": "^8.0.0" | ||
| }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
question: Why are they "peer dependencies"? I’m not super familiar with that.
| "private": true, | ||
| "version": "0.0.0", | ||
| "private": false, | ||
| "version": "1.0.0", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion: Let’s start with 0.1.0
CBenoit
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I’m not an expert on npm packages, but I’ve done some digging, and I have some questions. Let’s check that together.
I’m not able to build the npm packages locally by running the scripts, did you check that?
For ts-angular-client, the dist folder has a package.json:
The package.json in dist is the one containing the "exports" key and other publishing related keys, not the top-level one.
I think the "two package.json approach" is the preferred pattern for TypeScript packages. It ensures we only publish a clean JS/d.ts only package using the resulting artifacts found in the dist/ folder. Also avoid import {…} from 'package/dist' in favor of import {…} from 'package', avoid unnecessary dev metadata, etc.
suggestion: Keep the root package.json files private ("private": true). Keep the types, module, main, exports and other runtime dependencies in the generated dist/package.json file.
You can either use a build script, or the vite-plugin-static-copy vite plugin. At least for IronRDP and IronVNC we use the vite-plugin-static-copy approach, you can refer to it: https://github.com/Devolutions/IronRDP/tree/master/web-client/iron-remote-desktop
note: Make sure to keep the publish-related metadata in the dist/package.json file only. In my comments I mention the description key. This must be in dist/package.json.
| "dependencies": { | ||
| "vite-plugin-dts": "^4.5.3", | ||
| "vite-plugin-static-copy": "^2.3.0" | ||
| }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
issue?: Probably needs to be in devDependencies? Double check if these are development tools.
| "ts-node": "^10.9.2", | ||
| "vite-plugin-dts": "^4.3.0" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
issue: I’m pretty sure those are development tools.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
issue: Missing description field.
| "vite-plugin-bundle-css": "^0.1.1" | ||
| }, | ||
| "peerDependencies": { | ||
| "@devolutions/shadow-player": "workspace:*", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion: Refer to my suggestion about the "two package.json files" approach.
Mentioned that in one of my comments, but I would like some explanation on the rationale (mostly because I’m not familiar with that).
Note that it’s preferable to open multiple pull requests: one per change. For instance:
It’s much easier to review, and easier to track the changes properly. Overall it’s easier to quickly merge multiple smaller PRs. |
|
Thanks for the detailed feedback, Benoit! You're absolutely right, this should have been 3 separate PRs. I’ll make sure to keep future PRs smaller and more focused. I should've written better description in my PR description, but basically the gateway-api is used to fetch data. It used to be scattered, but my idea is to have a reusable API (I have not touched the previous code so other projects can still use what is there). For the shadow-player disconnect method, that one is just for proper cleanup. When testing with DVLS, I noticed WebSocket connections and video buffers stayed alive even after closing the dialog, so this makes sure everything is freed correctly. Regarding dependencies: I initially used peerDependencies because, from what I could see, they can help avoid duplicates and let users manage their versions (especially for something big like video.js). I wasn't sure how RDM handled packages, so I wanted to avoid duplications (having 2 video.js), but after looking into it more, modern package managers (npm 7+) dedupe automatically, and regular dependencies give a simpler install experience, so I made the change to switch to regular dependencies Right now I’m updating the packages to follow the two-package.json approach, working on that fix now |
private to public