mirror of
https://github.com/netbirdio/IronRDP.git
synced 2026-05-22 18:43:12 -07:00
refactor(web-client): refactor iron-remote-gui into iron-remote-desktop (#722)
This commit is contained in:
+7
-1
@@ -168,12 +168,18 @@ WebAssembly high-level bindings targeting web browsers.
|
||||
|
||||
This crate is an **API Boundary** (WASM module).
|
||||
|
||||
#### [`web-client/iron-remote-gui`](./web-client/iron-remote-gui)
|
||||
#### [`web-client/iron-remote-desktop`](./web-client/iron-remote-desktop)
|
||||
|
||||
Core frontend UI used by `iron-svelte-client` as a Web Component.
|
||||
|
||||
This crate is an **API Boundary**.
|
||||
|
||||
#### [`web-client/iron-remote-desktop-rdp`](./web-client/iron-remote-desktop-rdp)
|
||||
|
||||
Implementation of the TypeScript interfaces exposed by WebAssembly bindings from `ironrdp-web` and used by `iron-svelte-client`.
|
||||
|
||||
This crate is an **API Boundary**.
|
||||
|
||||
#### [`web-client/iron-svelte-client`](./web-client/iron-svelte-client)
|
||||
|
||||
Web-based frontend using `Svelte` and `Material` frameworks.
|
||||
|
||||
Generated
+13
@@ -2809,6 +2809,8 @@ dependencies = [
|
||||
"resize",
|
||||
"rgb",
|
||||
"semver",
|
||||
"serde",
|
||||
"serde-wasm-bindgen",
|
||||
"smallvec",
|
||||
"softbuffer",
|
||||
"tap",
|
||||
@@ -4668,6 +4670,17 @@ dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde-wasm-bindgen"
|
||||
version = "0.6.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8302e169f0eddcc139c70f139d19d6467353af16f9fce27e8c30158036a1e16b"
|
||||
dependencies = [
|
||||
"js-sys",
|
||||
"serde",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_bytes"
|
||||
version = "0.11.17"
|
||||
|
||||
@@ -45,6 +45,8 @@ web-sys = { version = "0.3", features = ["HtmlCanvasElement"] }
|
||||
js-sys = "0.3"
|
||||
gloo-net = { version = "0.6", default-features = false, features = ["websocket", "http", "io-util"] }
|
||||
gloo-timers = { version = "0.3", default-features = false, features = ["futures"] }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde-wasm-bindgen = "0.6"
|
||||
tracing-web = "0.1"
|
||||
|
||||
# Rendering
|
||||
|
||||
@@ -137,7 +137,7 @@ impl WasmClipboard {
|
||||
pub(crate) fn new(message_proxy: WasmClipboardMessageProxy, js_callbacks: JsClipboardCallbacks) -> Self {
|
||||
Self {
|
||||
local_clipboard: None,
|
||||
remote_clipboard: ClipboardTransaction::new(),
|
||||
remote_clipboard: ClipboardTransaction::construct(),
|
||||
proxy: message_proxy,
|
||||
js_callbacks,
|
||||
|
||||
@@ -505,7 +505,7 @@ impl WasmClipboard {
|
||||
} else {
|
||||
// If no initial clipboard callback was set, send empty format list instead
|
||||
return self.process_event(WasmClipboardBackendMessage::LocalClipboardChanged(
|
||||
ClipboardTransaction::new(),
|
||||
ClipboardTransaction::construct(),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ impl ClipboardTransaction {
|
||||
|
||||
#[wasm_bindgen]
|
||||
impl ClipboardTransaction {
|
||||
pub fn new() -> Self {
|
||||
pub fn construct() -> Self {
|
||||
Self { contents: Vec::new() }
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ use wasm_bindgen::prelude::*;
|
||||
|
||||
#[wasm_bindgen]
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum IronRdpErrorKind {
|
||||
pub enum RemoteDesktopErrorKind {
|
||||
/// Catch-all error kind
|
||||
General,
|
||||
/// Incorrect password used
|
||||
@@ -19,30 +19,30 @@ pub enum IronRdpErrorKind {
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub struct IronRdpError {
|
||||
kind: IronRdpErrorKind,
|
||||
pub struct RemoteDesktopError {
|
||||
kind: RemoteDesktopErrorKind,
|
||||
source: anyhow::Error,
|
||||
}
|
||||
|
||||
impl IronRdpError {
|
||||
pub fn with_kind(mut self, kind: IronRdpErrorKind) -> Self {
|
||||
impl RemoteDesktopError {
|
||||
pub fn with_kind(mut self, kind: RemoteDesktopErrorKind) -> Self {
|
||||
self.kind = kind;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
impl IronRdpError {
|
||||
impl RemoteDesktopError {
|
||||
pub fn backtrace(&self) -> String {
|
||||
format!("{:?}", self.source)
|
||||
}
|
||||
|
||||
pub fn kind(&self) -> IronRdpErrorKind {
|
||||
pub fn kind(&self) -> RemoteDesktopErrorKind {
|
||||
self.kind
|
||||
}
|
||||
}
|
||||
|
||||
impl From<connector::ConnectorError> for IronRdpError {
|
||||
impl From<connector::ConnectorError> for RemoteDesktopError {
|
||||
fn from(e: connector::ConnectorError) -> Self {
|
||||
use sspi::credssp::NStatusCode;
|
||||
|
||||
@@ -50,13 +50,13 @@ impl From<connector::ConnectorError> for IronRdpError {
|
||||
ConnectorErrorKind::Credssp(sspi::Error {
|
||||
nstatus: Some(NStatusCode::WRONG_PASSWORD),
|
||||
..
|
||||
}) => IronRdpErrorKind::WrongPassword,
|
||||
}) => RemoteDesktopErrorKind::WrongPassword,
|
||||
ConnectorErrorKind::Credssp(sspi::Error {
|
||||
nstatus: Some(NStatusCode::LOGON_FAILURE),
|
||||
..
|
||||
}) => IronRdpErrorKind::LogonFailure,
|
||||
ConnectorErrorKind::AccessDenied => IronRdpErrorKind::AccessDenied,
|
||||
_ => IronRdpErrorKind::General,
|
||||
}) => RemoteDesktopErrorKind::LogonFailure,
|
||||
ConnectorErrorKind::AccessDenied => RemoteDesktopErrorKind::AccessDenied,
|
||||
_ => RemoteDesktopErrorKind::General,
|
||||
};
|
||||
|
||||
Self {
|
||||
@@ -66,19 +66,19 @@ impl From<connector::ConnectorError> for IronRdpError {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ironrdp::session::SessionError> for IronRdpError {
|
||||
impl From<ironrdp::session::SessionError> for RemoteDesktopError {
|
||||
fn from(e: ironrdp::session::SessionError) -> Self {
|
||||
Self {
|
||||
kind: IronRdpErrorKind::General,
|
||||
kind: RemoteDesktopErrorKind::General,
|
||||
source: anyhow::Error::new(e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<anyhow::Error> for IronRdpError {
|
||||
impl From<anyhow::Error> for RemoteDesktopError {
|
||||
fn from(e: anyhow::Error) -> Self {
|
||||
Self {
|
||||
kind: IronRdpErrorKind::General,
|
||||
kind: RemoteDesktopErrorKind::General,
|
||||
source: e,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ pub struct DeviceEvent(pub(crate) Operation);
|
||||
|
||||
#[wasm_bindgen]
|
||||
impl DeviceEvent {
|
||||
pub fn new_mouse_button_pressed(button: u8) -> Self {
|
||||
pub fn mouse_button_pressed(button: u8) -> Self {
|
||||
match MouseButton::from_web_button(button) {
|
||||
Some(button) => Self(Operation::MouseButtonPressed(button)),
|
||||
None => {
|
||||
@@ -18,7 +18,7 @@ impl DeviceEvent {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_mouse_button_released(button: u8) -> Self {
|
||||
pub fn mouse_button_released(button: u8) -> Self {
|
||||
match MouseButton::from_web_button(button) {
|
||||
Some(button) => Self(Operation::MouseButtonReleased(button)),
|
||||
None => {
|
||||
@@ -28,30 +28,30 @@ impl DeviceEvent {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_mouse_move(x: u16, y: u16) -> Self {
|
||||
pub fn mouse_move(x: u16, y: u16) -> Self {
|
||||
Self(Operation::MouseMove(MousePosition { x, y }))
|
||||
}
|
||||
|
||||
pub fn new_wheel_rotations(vertical: bool, rotation_units: i16) -> Self {
|
||||
pub fn wheel_rotations(vertical: bool, rotation_units: i16) -> Self {
|
||||
Self(Operation::WheelRotations(WheelRotations {
|
||||
is_vertical: vertical,
|
||||
rotation_units,
|
||||
}))
|
||||
}
|
||||
|
||||
pub fn new_key_pressed(scancode: u16) -> Self {
|
||||
pub fn key_pressed(scancode: u16) -> Self {
|
||||
Self(Operation::KeyPressed(Scancode::from_u16(scancode)))
|
||||
}
|
||||
|
||||
pub fn new_key_released(scancode: u16) -> Self {
|
||||
pub fn key_released(scancode: u16) -> Self {
|
||||
Self(Operation::KeyReleased(Scancode::from_u16(scancode)))
|
||||
}
|
||||
|
||||
pub fn new_unicode_pressed(unicode: char) -> Self {
|
||||
pub fn unicode_pressed(unicode: char) -> Self {
|
||||
Self(Operation::UnicodeKeyPressed(unicode))
|
||||
}
|
||||
|
||||
pub fn new_unicode_released(unicode: char) -> Self {
|
||||
pub fn unicode_released(unicode: char) -> Self {
|
||||
Self(Operation::UnicodeKeyReleased(unicode))
|
||||
}
|
||||
}
|
||||
@@ -61,7 +61,7 @@ pub struct InputTransaction(pub(crate) SmallVec<[Operation; 3]>);
|
||||
|
||||
#[wasm_bindgen]
|
||||
impl InputTransaction {
|
||||
pub fn new() -> Self {
|
||||
pub fn construct() -> Self {
|
||||
Self(SmallVec::new())
|
||||
}
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ mod session;
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn ironrdp_init(log_level: &str) {
|
||||
pub fn iron_init(log_level: &str) {
|
||||
// When the `console_error_panic_hook` feature is enabled, we can call the
|
||||
// `set_panic_hook` function at least once during initialization, and then
|
||||
// we will get better error messages if our code ever panics.
|
||||
@@ -69,7 +69,7 @@ pub struct DesktopSize {
|
||||
|
||||
#[wasm_bindgen]
|
||||
impl DesktopSize {
|
||||
pub fn new(width: u16, height: u16) -> Self {
|
||||
pub fn construct(width: u16, height: u16) -> Self {
|
||||
DesktopSize { width, height }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ use ironrdp::session::{fast_path, ActiveStage, ActiveStageOutput, GracefulDiscon
|
||||
use ironrdp_core::WriteBuf;
|
||||
use ironrdp_futures::{single_sequence_step_read, FramedWrite};
|
||||
use rgb::AsPixels as _;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use tap::prelude::*;
|
||||
use wasm_bindgen::prelude::*;
|
||||
use wasm_bindgen_futures::spawn_local;
|
||||
@@ -36,7 +37,7 @@ use web_sys::HtmlCanvasElement;
|
||||
|
||||
use crate::canvas::Canvas;
|
||||
use crate::clipboard::{ClipboardTransaction, WasmClipboard, WasmClipboardBackend, WasmClipboardBackendMessage};
|
||||
use crate::error::{IronRdpError, IronRdpErrorKind};
|
||||
use crate::error::{RemoteDesktopError, RemoteDesktopErrorKind};
|
||||
use crate::image::extract_partial_image;
|
||||
use crate::input::InputTransaction;
|
||||
use crate::network_client::WasmNetworkClient;
|
||||
@@ -102,7 +103,7 @@ impl Default for SessionBuilderInner {
|
||||
|
||||
#[wasm_bindgen]
|
||||
impl SessionBuilder {
|
||||
pub fn new() -> SessionBuilder {
|
||||
pub fn construct() -> SessionBuilder {
|
||||
Self(Rc::new(RefCell::new(SessionBuilderInner::default())))
|
||||
}
|
||||
|
||||
@@ -146,18 +147,6 @@ impl SessionBuilder {
|
||||
self.clone()
|
||||
}
|
||||
|
||||
/// Optional
|
||||
pub fn pcb(&self, pcb: String) -> SessionBuilder {
|
||||
self.0.borrow_mut().pcb = Some(pcb);
|
||||
self.clone()
|
||||
}
|
||||
|
||||
/// Optional
|
||||
pub fn kdc_proxy_url(&self, kdc_proxy_url: Option<String>) -> SessionBuilder {
|
||||
self.0.borrow_mut().kdc_proxy_url = kdc_proxy_url;
|
||||
self.clone()
|
||||
}
|
||||
|
||||
/// Optional
|
||||
pub fn desktop_size(&self, desktop_size: DesktopSize) -> SessionBuilder {
|
||||
self.0.borrow_mut().desktop_size = desktop_size;
|
||||
@@ -216,13 +205,22 @@ impl SessionBuilder {
|
||||
self.clone()
|
||||
}
|
||||
|
||||
/// Optional
|
||||
pub fn use_display_control(&self) -> SessionBuilder {
|
||||
self.0.borrow_mut().use_display_control = true;
|
||||
pub fn extension(&self, value: JsValue) -> SessionBuilder {
|
||||
match serde_wasm_bindgen::from_value::<Extension>(value) {
|
||||
Ok(value) => match value {
|
||||
Extension::KdcProxyUrl(kdc_proxy_url) => self.0.borrow_mut().kdc_proxy_url = Some(kdc_proxy_url),
|
||||
Extension::Pcb(pcb) => self.0.borrow_mut().pcb = Some(pcb),
|
||||
Extension::DisplayControl(use_display_control) => {
|
||||
self.0.borrow_mut().use_display_control = use_display_control
|
||||
}
|
||||
},
|
||||
Err(error) => error!(%error, "Unsupported extension value"),
|
||||
}
|
||||
|
||||
self.clone()
|
||||
}
|
||||
|
||||
pub async fn connect(&self) -> Result<Session, IronRdpError> {
|
||||
pub async fn connect(&self) -> Result<Session, RemoteDesktopError> {
|
||||
let (
|
||||
username,
|
||||
destination,
|
||||
@@ -297,11 +295,11 @@ impl SessionBuilder {
|
||||
loop {
|
||||
match ws.state() {
|
||||
websocket::State::Closing | websocket::State::Closed => {
|
||||
return Err(IronRdpError::from(anyhow::anyhow!(
|
||||
"Failed to connect to {proxy_address} (WebSocket is `{:?}`)",
|
||||
return Err(RemoteDesktopError::from(anyhow::anyhow!(
|
||||
"failed to connect to {proxy_address} (WebSocket is `{:?}`)",
|
||||
ws.state()
|
||||
))
|
||||
.with_kind(IronRdpErrorKind::ProxyConnect));
|
||||
.with_kind(RemoteDesktopErrorKind::ProxyConnect));
|
||||
}
|
||||
websocket::State::Connecting => {
|
||||
trace!("WebSocket is connecting to proxy at {proxy_address}...");
|
||||
@@ -354,6 +352,13 @@ impl SessionBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
enum Extension {
|
||||
KdcProxyUrl(String),
|
||||
Pcb(String),
|
||||
DisplayControl(bool),
|
||||
}
|
||||
|
||||
pub(crate) type FastPathInputEvents = smallvec::SmallVec<[FastPathInputEvent; 2]>;
|
||||
|
||||
#[derive(Debug)]
|
||||
@@ -412,7 +417,7 @@ pub struct Session {
|
||||
|
||||
#[wasm_bindgen]
|
||||
impl Session {
|
||||
pub async fn run(&self) -> Result<SessionTerminationInfo, IronRdpError> {
|
||||
pub async fn run(&self) -> Result<SessionTerminationInfo, RemoteDesktopError> {
|
||||
let rdp_reader = self
|
||||
.rdp_reader
|
||||
.borrow_mut()
|
||||
@@ -707,17 +712,17 @@ impl Session {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn apply_inputs(&self, transaction: InputTransaction) -> Result<(), IronRdpError> {
|
||||
pub fn apply_inputs(&self, transaction: InputTransaction) -> Result<(), RemoteDesktopError> {
|
||||
let inputs = self.input_database.borrow_mut().apply(transaction);
|
||||
self.h_send_inputs(inputs)
|
||||
}
|
||||
|
||||
pub fn release_all_inputs(&self) -> Result<(), IronRdpError> {
|
||||
pub fn release_all_inputs(&self) -> Result<(), RemoteDesktopError> {
|
||||
let inputs = self.input_database.borrow_mut().release_all();
|
||||
self.h_send_inputs(inputs)
|
||||
}
|
||||
|
||||
fn h_send_inputs(&self, inputs: smallvec::SmallVec<[FastPathInputEvent; 2]>) -> Result<(), IronRdpError> {
|
||||
fn h_send_inputs(&self, inputs: smallvec::SmallVec<[FastPathInputEvent; 2]>) -> Result<(), RemoteDesktopError> {
|
||||
if !inputs.is_empty() {
|
||||
trace!("Inputs: {inputs:?}");
|
||||
|
||||
@@ -735,7 +740,7 @@ impl Session {
|
||||
num_lock: bool,
|
||||
caps_lock: bool,
|
||||
kana_lock: bool,
|
||||
) -> Result<(), IronRdpError> {
|
||||
) -> Result<(), RemoteDesktopError> {
|
||||
use ironrdp::pdu::input::fast_path::FastPathInput;
|
||||
|
||||
let event = ironrdp::input::synchronize_event(scroll_lock, num_lock, caps_lock, kana_lock);
|
||||
@@ -750,7 +755,7 @@ impl Session {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn shutdown(&self) -> Result<(), IronRdpError> {
|
||||
pub fn shutdown(&self) -> Result<(), RemoteDesktopError> {
|
||||
self.input_events_tx
|
||||
.unbounded_send(RdpInputEvent::TerminateSession)
|
||||
.context("failed to send terminate session event to writer task")?;
|
||||
@@ -758,7 +763,7 @@ impl Session {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn on_clipboard_paste(&self, content: ClipboardTransaction) -> Result<(), IronRdpError> {
|
||||
pub async fn on_clipboard_paste(&self, content: ClipboardTransaction) -> Result<(), RemoteDesktopError> {
|
||||
self.input_events_tx
|
||||
.unbounded_send(RdpInputEvent::ClipboardBackend(
|
||||
WasmClipboardBackendMessage::LocalClipboardChanged(content),
|
||||
@@ -768,7 +773,7 @@ impl Session {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn set_cursor_style(&self, style: CursorStyle) -> Result<(), IronRdpError> {
|
||||
fn set_cursor_style(&self, style: CursorStyle) -> Result<(), RemoteDesktopError> {
|
||||
let (kind, data, hotspot_x, hotspot_y) = match style {
|
||||
CursorStyle::Default => ("default", None, None, None),
|
||||
CursorStyle::Hidden => ("hidden", None, None, None),
|
||||
@@ -818,6 +823,10 @@ impl Session {
|
||||
// plain scancode events are allowed to function correctly).
|
||||
false
|
||||
}
|
||||
|
||||
pub fn extension_call(_value: JsValue) -> Result<JsValue, RemoteDesktopError> {
|
||||
Ok(JsValue::null())
|
||||
}
|
||||
}
|
||||
|
||||
fn build_config(
|
||||
@@ -913,7 +922,7 @@ async fn connect(
|
||||
clipboard_backend,
|
||||
use_display_control,
|
||||
}: ConnectParams,
|
||||
) -> Result<(connector::ConnectionResult, WebSocket), IronRdpError> {
|
||||
) -> Result<(connector::ConnectionResult, WebSocket), RemoteDesktopError> {
|
||||
let mut framed = ironrdp_futures::LocalFuturesFramed::new(ws);
|
||||
|
||||
let mut connector = ClientConnector::new(config);
|
||||
@@ -960,7 +969,7 @@ async fn connect_rdcleanpath<S>(
|
||||
destination: String,
|
||||
proxy_auth_token: String,
|
||||
pcb: Option<String>,
|
||||
) -> Result<(ironrdp_futures::Upgraded, Vec<u8>), IronRdpError>
|
||||
) -> Result<(ironrdp_futures::Upgraded, Vec<u8>), RemoteDesktopError>
|
||||
where
|
||||
S: ironrdp_futures::FramedRead + FramedWrite,
|
||||
{
|
||||
@@ -1039,10 +1048,10 @@ where
|
||||
server_addr,
|
||||
} => (x224_connection_response, server_cert_chain, server_addr),
|
||||
ironrdp_rdcleanpath::RDCleanPath::Err(error) => {
|
||||
return Err(
|
||||
IronRdpError::from(anyhow::anyhow!("received an RDCleanPath error: {error}"))
|
||||
.with_kind(IronRdpErrorKind::RDCleanPath),
|
||||
);
|
||||
return Err(RemoteDesktopError::from(
|
||||
anyhow::Error::new(error).context("received an RDCleanPath error"),
|
||||
)
|
||||
.with_kind(RemoteDesktopErrorKind::RDCleanPath));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
IronRDP also supports the web browser as a first class target.
|
||||
|
||||
See the [iron-remote-gui](./iron-remote-gui) for the reusable Web Component, and [iron-svelte-client](./iron-svelte-client) for a demonstration.
|
||||
See the [iron-remote-desktop](./iron-remote-desktop) for the reusable Web Component, and [iron-svelte-client](./iron-svelte-client) for a demonstration.
|
||||
|
||||
Note that the demonstration client is not intended to be used in production as-is.
|
||||
Devolutions is shipping well-integrated, production-ready IronRDP web clients as part of:
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
node_modules/
|
||||
.DS_Store
|
||||
.env
|
||||
.env.*
|
||||
!.env.example
|
||||
|
||||
/package
|
||||
/build
|
||||
/static/bearcss
|
||||
/static/material-icons
|
||||
/dist
|
||||
# Ignore files for PNPM, NPM and YARN
|
||||
pnpm-lock.yaml
|
||||
package-lock.json
|
||||
yarn.lock
|
||||
@@ -0,0 +1,19 @@
|
||||
# Prettier:
|
||||
# - https://prettier.io/docs/en/options
|
||||
---
|
||||
useTabs: false
|
||||
tabWidth: 4
|
||||
singleQuote: true
|
||||
semi: true
|
||||
trailingComma: all
|
||||
printWidth: 120
|
||||
|
||||
overrides:
|
||||
- files:
|
||||
- '*.yml'
|
||||
- '*.yaml'
|
||||
- '*.json'
|
||||
- '*.html'
|
||||
- '*.md'
|
||||
options:
|
||||
tabWidth: 2
|
||||
@@ -0,0 +1,23 @@
|
||||
# Iron Remote Desktop RDP
|
||||
|
||||
This is implementation of `RemoteDesktopModule` interface from [iron-remote-desktop](../iron-remote-desktop) for RDP connection.
|
||||
|
||||
## Development
|
||||
|
||||
Make your modification in the source code then use [iron-svelte-client](../iron-svelte-client) to test.
|
||||
|
||||
## Build
|
||||
|
||||
Run `npm run build`
|
||||
|
||||
## Usage
|
||||
|
||||
As member of the Devolutions organization, you can import the Web Component from JFrog Artifactory by running the following npm command:
|
||||
|
||||
```shell
|
||||
$ npm install @devolutions/iron-remote-desktop-rdp
|
||||
```
|
||||
|
||||
Otherwise, you can run `npm install` targeting the `dist/` folder directly.
|
||||
|
||||
Import the `iron-remote-desktop-rdp.umd.cjs` from `node_modules/` folder.
|
||||
@@ -0,0 +1,80 @@
|
||||
import typescriptEslint from '@typescript-eslint/eslint-plugin';
|
||||
import globals from 'globals';
|
||||
import tsParser from '@typescript-eslint/parser';
|
||||
import path from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import js from '@eslint/js';
|
||||
import { FlatCompat } from '@eslint/eslintrc';
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
const compat = new FlatCompat({
|
||||
baseDirectory: __dirname,
|
||||
recommendedConfig: js.configs.recommended,
|
||||
allConfig: js.configs.all,
|
||||
});
|
||||
|
||||
export default [
|
||||
{
|
||||
ignores: [
|
||||
'**/*.cjs',
|
||||
'**/.DS_Store',
|
||||
'**/node_modules',
|
||||
'build',
|
||||
'package',
|
||||
'**/.env',
|
||||
'**/.env.*',
|
||||
'!**/.env.example',
|
||||
'**/pnpm-lock.yaml',
|
||||
'**/package-lock.json',
|
||||
'**/yarn.lock',
|
||||
],
|
||||
},
|
||||
...compat.extends('eslint:recommended', 'plugin:@typescript-eslint/recommended', 'plugin:prettier/recommended'),
|
||||
{
|
||||
plugins: {
|
||||
'@typescript-eslint': typescriptEslint,
|
||||
},
|
||||
|
||||
languageOptions: {
|
||||
globals: {
|
||||
...globals.browser,
|
||||
...globals.node,
|
||||
},
|
||||
|
||||
parser: tsParser,
|
||||
ecmaVersion: 2020,
|
||||
sourceType: 'module',
|
||||
|
||||
parserOptions: {
|
||||
project: './tsconfig.json',
|
||||
},
|
||||
},
|
||||
|
||||
rules: {
|
||||
strict: 2,
|
||||
|
||||
'@typescript-eslint/no-unused-vars': [
|
||||
'error',
|
||||
{
|
||||
argsIgnorePattern: '^_',
|
||||
},
|
||||
],
|
||||
|
||||
'@typescript-eslint/strict-boolean-expressions': [
|
||||
2,
|
||||
{
|
||||
allowString: false,
|
||||
allowNumber: false,
|
||||
},
|
||||
],
|
||||
|
||||
'prettier/prettier': [
|
||||
'error',
|
||||
{
|
||||
endOfLine: 'auto',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
];
|
||||
+3995
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,51 @@
|
||||
{
|
||||
"name": "@devolutions/iron-remote-desktop-rdp",
|
||||
"author": "Nicolas Girot",
|
||||
"email": "ngirot@devolutions.net",
|
||||
"contributors": [
|
||||
"Benoit Cortier",
|
||||
"Irving Ou",
|
||||
"Vladislav Nikonov",
|
||||
"Zacharia Ellaham",
|
||||
"Alexandr Yusuk"
|
||||
],
|
||||
"description": "Web Component providing agnostic implementation for Iron Wasm base client",
|
||||
"version": "0.0.0",
|
||||
"type": "module",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "npm run pre-build && vite",
|
||||
"build": "npm run pre-build && vite build",
|
||||
"build-alone": "vite build",
|
||||
"pre-build": "node ./pre-build.js",
|
||||
"preview": "vite preview",
|
||||
"check": "tsc --noEmit",
|
||||
"check:dist": "tsc ./dist/index.d.ts --noEmit",
|
||||
"check:watch": "tsc --watch --noEmit",
|
||||
"lint": "npm run lint:prettier && npm run lint:eslint",
|
||||
"lint:prettier": "prettier --check .",
|
||||
"lint:eslint": "eslint src/**",
|
||||
"format": "prettier --write ."
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/eslintrc": "^3.3.0",
|
||||
"@eslint/js": "^9.21.0",
|
||||
"@types/ua-parser-js": "^0.7.36",
|
||||
"@typescript-eslint/eslint-plugin": "^8.25.0",
|
||||
"eslint": "^9.21.0",
|
||||
"eslint-config-prettier": "^9.0.0",
|
||||
"eslint-plugin-prettier": "^5.0.1",
|
||||
"globals": "^16.0.0",
|
||||
"prettier": "^3.1.0",
|
||||
"tslib": "^2.4.1",
|
||||
"typescript": "~5.7.2",
|
||||
"vite": "^6.2.0",
|
||||
"vite-plugin-dts": "^4.5.0",
|
||||
"vite-plugin-top-level-await": "^1.2.2",
|
||||
"vite-plugin-wasm": "^3.1.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"rxjs": "^6.6.7",
|
||||
"ua-parser-js": "^1.0.33"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
import { spawn } from 'child_process';
|
||||
|
||||
const run = async (command, cwd) => {
|
||||
try {
|
||||
const buildCommand = spawn(command, {
|
||||
stdio: 'pipe',
|
||||
shell: true,
|
||||
cwd: cwd,
|
||||
});
|
||||
|
||||
buildCommand.stdout.on('data', (data) => {
|
||||
console.log(`${data}`);
|
||||
});
|
||||
|
||||
buildCommand.stderr.on('data', (data) => {
|
||||
console.error(`${data}`);
|
||||
});
|
||||
|
||||
const exitCode = await new Promise((resolve, reject) => {
|
||||
buildCommand.on('close', (code) => {
|
||||
if (code !== 0) {
|
||||
reject(new Error(`Process exited with non-zero code: ${code}`));
|
||||
}
|
||||
resolve(code);
|
||||
});
|
||||
});
|
||||
|
||||
console.log(`Child process exited with code: ${exitCode}`);
|
||||
} catch (err) {
|
||||
console.error(`Process run failed: ${err}`);
|
||||
}
|
||||
};
|
||||
|
||||
await run('cargo xtask web build', '../../');
|
||||
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"name": "@devolutions/iron-remote-desktop-rdp",
|
||||
"author": "Nicolas Girot",
|
||||
"email": "ngirot@devolutions.net",
|
||||
"contributors": [
|
||||
"Benoit Cortier",
|
||||
"Irving Ou",
|
||||
"Vladislav Nikonov",
|
||||
"Zacharia Ellaham"
|
||||
],
|
||||
"description": "Web Component providing agnostic implementation for Iron Wasm base client.",
|
||||
"version": "0.13.1",
|
||||
"main": "iron-remote-desktop-rdp.js",
|
||||
"types": "index.d.ts",
|
||||
"files": [
|
||||
"iron-remote-desktop-rdp.js",
|
||||
"index.d.ts"
|
||||
],
|
||||
"dependencies": {
|
||||
"rxjs": "^6.6.7"
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user