@ -0,0 +1,3 @@
|
||||
/target
|
||||
/node_modules
|
||||
/Cargo.lock
|
@ -0,0 +1,14 @@
|
||||
[package]
|
||||
name = "tauri-plugin-websocket"
|
||||
version = "0.1.0"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
serde = "1.0"
|
||||
serde_json = "1.0"
|
||||
thiserror = "1.0"
|
||||
rand = "0.8"
|
||||
tauri = "1.0.0-beta.8"
|
||||
futures-util = "0.3"
|
||||
tokio = { version = "1.11", features = ["net", "sync"] }
|
||||
tokio-tungstenite = { version = "0.15", features = ["native-tls"] }
|
@ -0,0 +1,5 @@
|
||||
node_modules/
|
||||
public/build/
|
||||
public/index.tauri.html
|
||||
|
||||
example.stronghold
|
@ -0,0 +1,3 @@
|
||||
{
|
||||
"recommendations": ["svelte.svelte-vscode"]
|
||||
}
|
@ -0,0 +1,105 @@
|
||||
*Looking for a shareable component template? Go here --> [sveltejs/component-template](https://github.com/sveltejs/component-template)*
|
||||
|
||||
---
|
||||
|
||||
# svelte app
|
||||
|
||||
This is a project template for [Svelte](https://svelte.dev) apps. It lives at https://github.com/sveltejs/template.
|
||||
|
||||
To create a new project based on this template using [degit](https://github.com/Rich-Harris/degit):
|
||||
|
||||
```bash
|
||||
npx degit sveltejs/template svelte-app
|
||||
cd svelte-app
|
||||
```
|
||||
|
||||
*Note that you will need to have [Node.js](https://nodejs.org) installed.*
|
||||
|
||||
|
||||
## Get started
|
||||
|
||||
Install the dependencies...
|
||||
|
||||
```bash
|
||||
cd svelte-app
|
||||
npm install
|
||||
```
|
||||
|
||||
...then start [Rollup](https://rollupjs.org):
|
||||
|
||||
```bash
|
||||
npm run dev
|
||||
```
|
||||
|
||||
Navigate to [localhost:5000](http://localhost:5000). You should see your app running. Edit a component file in `src`, save it, and reload the page to see your changes.
|
||||
|
||||
By default, the server will only respond to requests from localhost. To allow connections from other computers, edit the `sirv` commands in package.json to include the option `--host 0.0.0.0`.
|
||||
|
||||
If you're using [Visual Studio Code](https://code.visualstudio.com/) we recommend installing the official extension [Svelte for VS Code](https://marketplace.visualstudio.com/items?itemName=svelte.svelte-vscode). If you are using other editors you may need to install a plugin in order to get syntax highlighting and intellisense.
|
||||
|
||||
## Building and running in production mode
|
||||
|
||||
To create an optimised version of the app:
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
```
|
||||
|
||||
You can run the newly built app with `npm run start`. This uses [sirv](https://github.com/lukeed/sirv), which is included in your package.json's `dependencies` so that the app will work when you deploy to platforms like [Heroku](https://heroku.com).
|
||||
|
||||
|
||||
## Single-page app mode
|
||||
|
||||
By default, sirv will only respond to requests that match files in `public`. This is to maximise compatibility with static fileservers, allowing you to deploy your app anywhere.
|
||||
|
||||
If you're building a single-page app (SPA) with multiple routes, sirv needs to be able to respond to requests for *any* path. You can make it so by editing the `"start"` command in package.json:
|
||||
|
||||
```js
|
||||
"start": "sirv public --single"
|
||||
```
|
||||
|
||||
## Using TypeScript
|
||||
|
||||
This template comes with a script to set up a TypeScript development environment, you can run it immediately after cloning the template with:
|
||||
|
||||
```bash
|
||||
node scripts/setupTypeScript.js
|
||||
```
|
||||
|
||||
Or remove the script via:
|
||||
|
||||
```bash
|
||||
rm scripts/setupTypeScript.js
|
||||
```
|
||||
|
||||
## Deploying to the web
|
||||
|
||||
### With [Vercel](https://vercel.com)
|
||||
|
||||
Install `vercel` if you haven't already:
|
||||
|
||||
```bash
|
||||
npm install -g vercel
|
||||
```
|
||||
|
||||
Then, from within your project folder:
|
||||
|
||||
```bash
|
||||
cd public
|
||||
vercel deploy --name my-project
|
||||
```
|
||||
|
||||
### With [surge](https://surge.sh/)
|
||||
|
||||
Install `surge` if you haven't already:
|
||||
|
||||
```bash
|
||||
npm install -g surge
|
||||
```
|
||||
|
||||
Then, from within your project folder:
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
surge public my-project.surge.sh
|
||||
```
|
@ -0,0 +1,32 @@
|
||||
{
|
||||
"name": "svelte-app",
|
||||
"version": "1.0.0",
|
||||
"scripts": {
|
||||
"build": "rollup -c",
|
||||
"dev": "rollup -c -w",
|
||||
"start": "sirv public",
|
||||
"validate": "svelte-check",
|
||||
"tauri": "tauri"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@rollup/plugin-commonjs": "^18.0.0",
|
||||
"@rollup/plugin-node-resolve": "^11.2.0",
|
||||
"@rollup/plugin-typescript": "^8.2.0",
|
||||
"@tauri-apps/cli": "^1.0.0-beta.8",
|
||||
"@tsconfig/svelte": "^1.0.0",
|
||||
"rollup": "^2.45",
|
||||
"rollup-plugin-css-only": "^3.1.0",
|
||||
"rollup-plugin-livereload": "^2.0.0",
|
||||
"rollup-plugin-svelte": "^7.0.0",
|
||||
"rollup-plugin-terser": "^7.0.0",
|
||||
"svelte": "^3.0.0",
|
||||
"svelte-check": "^1.0.0",
|
||||
"svelte-preprocess": "^4.0.0",
|
||||
"tslib": "^2.0.0",
|
||||
"typescript": "^3.9.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"sirv-cli": "^1.0.0",
|
||||
"tauri-plugin-websocket-api": "link:../../"
|
||||
}
|
||||
}
|
After Width: | Height: | Size: 3.1 KiB |
@ -0,0 +1,63 @@
|
||||
html, body {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
color: #333;
|
||||
margin: 0;
|
||||
padding: 8px;
|
||||
box-sizing: border-box;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
|
||||
}
|
||||
|
||||
a {
|
||||
color: rgb(0,100,200);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
a:visited {
|
||||
color: rgb(0,80,160);
|
||||
}
|
||||
|
||||
label {
|
||||
display: block;
|
||||
}
|
||||
|
||||
input, button, select, textarea {
|
||||
font-family: inherit;
|
||||
font-size: inherit;
|
||||
-webkit-padding: 0.4em 0;
|
||||
padding: 0.4em;
|
||||
margin: 0 0 0.5em 0;
|
||||
box-sizing: border-box;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
input:disabled {
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
button {
|
||||
color: #333;
|
||||
background-color: #f4f4f4;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
button:disabled {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
button:not(:disabled):active {
|
||||
background-color: #ddd;
|
||||
}
|
||||
|
||||
button:focus {
|
||||
border-color: #666;
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset='utf-8'>
|
||||
<meta name='viewport' content='width=device-width,initial-scale=1'>
|
||||
|
||||
<title>Svelte app</title>
|
||||
|
||||
<link rel='icon' type='image/png' href='favicon.png'>
|
||||
<link rel='stylesheet' href='global.css'>
|
||||
<link rel='stylesheet' href='build/bundle.css'>
|
||||
|
||||
<script defer src='build/bundle.js'></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
</body>
|
||||
|
||||
</html>
|
@ -0,0 +1,83 @@
|
||||
import svelte from 'rollup-plugin-svelte';
|
||||
import commonjs from '@rollup/plugin-commonjs';
|
||||
import resolve from '@rollup/plugin-node-resolve';
|
||||
import livereload from 'rollup-plugin-livereload';
|
||||
import { terser } from 'rollup-plugin-terser';
|
||||
import sveltePreprocess from 'svelte-preprocess';
|
||||
import typescript from '@rollup/plugin-typescript';
|
||||
import css from 'rollup-plugin-css-only';
|
||||
|
||||
const production = !process.env.ROLLUP_WATCH;
|
||||
|
||||
function serve() {
|
||||
let server;
|
||||
|
||||
function toExit() {
|
||||
if (server) server.kill(0);
|
||||
}
|
||||
|
||||
return {
|
||||
writeBundle() {
|
||||
if (server) return;
|
||||
server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], {
|
||||
stdio: ['ignore', 'inherit', 'inherit'],
|
||||
shell: true
|
||||
});
|
||||
|
||||
process.on('SIGTERM', toExit);
|
||||
process.on('exit', toExit);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export default {
|
||||
input: 'src/main.ts',
|
||||
output: {
|
||||
sourcemap: true,
|
||||
format: 'iife',
|
||||
name: 'app',
|
||||
file: 'public/build/bundle.js'
|
||||
},
|
||||
plugins: [
|
||||
svelte({
|
||||
preprocess: sveltePreprocess(),
|
||||
compilerOptions: {
|
||||
// enable run-time checks when not in production
|
||||
dev: !production
|
||||
}
|
||||
}),
|
||||
// we'll extract any component CSS out into
|
||||
// a separate file - better for performance
|
||||
css({ output: 'bundle.css' }),
|
||||
|
||||
// If you have external dependencies installed from
|
||||
// npm, you'll most likely need these plugins. In
|
||||
// some cases you'll need additional configuration -
|
||||
// consult the documentation for details:
|
||||
// https://github.com/rollup/plugins/tree/master/packages/commonjs
|
||||
resolve({
|
||||
browser: true,
|
||||
dedupe: ['svelte']
|
||||
}),
|
||||
commonjs(),
|
||||
typescript({
|
||||
sourceMap: !production,
|
||||
inlineSources: !production
|
||||
}),
|
||||
|
||||
// In dev mode, call `npm run start` once
|
||||
// the bundle has been generated
|
||||
!production && serve(),
|
||||
|
||||
// Watch the `public` directory and refresh the
|
||||
// browser on changes when not in production
|
||||
!production && livereload('public'),
|
||||
|
||||
// If we're building for production (npm run build
|
||||
// instead of npm run dev), minify
|
||||
production && terser()
|
||||
],
|
||||
watch: {
|
||||
clearScreen: false
|
||||
}
|
||||
};
|
@ -0,0 +1,7 @@
|
||||
# Generated by Cargo
|
||||
# will have compiled files and executables
|
||||
/target/
|
||||
WixTools
|
||||
|
||||
# These are backup files generated by rustfmt
|
||||
**/*.rs.bk
|
@ -0,0 +1,23 @@
|
||||
[package]
|
||||
name = "app"
|
||||
version = "0.1.0"
|
||||
description = "A Tauri App"
|
||||
authors = [ "Tauri Programme within The Commons Conservancy" ]
|
||||
repository = ""
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
serde_json = "1.0"
|
||||
serde = { version = "1.0", features = [ "derive" ] }
|
||||
tauri = { version = "1.0.0-beta.5", features = ["api-all"] }
|
||||
tokio = { version = "1.11", features = ["net"] }
|
||||
futures-util = "0.3"
|
||||
tauri-plugin-websocket = { path = "../../../" }
|
||||
tokio-tungstenite = "0.15"
|
||||
|
||||
[build-dependencies]
|
||||
tauri-build = "1.0.0-beta.3"
|
||||
|
||||
[features]
|
||||
default = [ "custom-protocol" ]
|
||||
custom-protocol = [ "tauri/custom-protocol" ]
|
@ -0,0 +1,3 @@
|
||||
fn main() {
|
||||
tauri_build::build()
|
||||
}
|
After Width: | Height: | Size: 16 KiB |
After Width: | Height: | Size: 37 KiB |
After Width: | Height: | Size: 2.3 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 18 KiB |
After Width: | Height: | Size: 19 KiB |
After Width: | Height: | Size: 41 KiB |
After Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 45 KiB |
After Width: | Height: | Size: 3.7 KiB |
After Width: | Height: | Size: 7.2 KiB |
After Width: | Height: | Size: 9.6 KiB |
After Width: | Height: | Size: 4.4 KiB |
After Width: | Height: | Size: 56 KiB |
After Width: | Height: | Size: 88 KiB |
@ -0,0 +1,13 @@
|
||||
max_width = 100
|
||||
hard_tabs = false
|
||||
tab_spaces = 2
|
||||
newline_style = "Auto"
|
||||
use_small_heuristics = "Default"
|
||||
reorder_imports = true
|
||||
reorder_modules = true
|
||||
remove_nested_parens = true
|
||||
edition = "2018"
|
||||
merge_derives = true
|
||||
use_try_shorthand = false
|
||||
use_field_init_shorthand = false
|
||||
force_explicit_abi = true
|
@ -0,0 +1,40 @@
|
||||
#![cfg_attr(
|
||||
all(not(debug_assertions), target_os = "windows"),
|
||||
windows_subsystem = "windows"
|
||||
)]
|
||||
|
||||
use futures_util::StreamExt;
|
||||
use tauri_plugin_websocket::TauriWebsocket;
|
||||
use tokio::net::{TcpListener, TcpStream};
|
||||
|
||||
async fn start_server() {
|
||||
let addr = "127.0.0.1:8080".to_string();
|
||||
|
||||
// Create the event loop and TCP listener we'll accept connections on.
|
||||
let try_socket = TcpListener::bind(&addr).await;
|
||||
let listener = try_socket.expect("Failed to bind");
|
||||
|
||||
while let Ok((stream, _)) = listener.accept().await {
|
||||
tokio::spawn(accept_connection(stream));
|
||||
}
|
||||
}
|
||||
|
||||
async fn accept_connection(stream: TcpStream) {
|
||||
let ws_stream = tokio_tungstenite::accept_async(stream)
|
||||
.await
|
||||
.expect("Error during the websocket handshake occurred");
|
||||
|
||||
let (write, read) = ws_stream.split();
|
||||
read
|
||||
.forward(write)
|
||||
.await
|
||||
.expect("Failed to forward message")
|
||||
}
|
||||
|
||||
fn main() {
|
||||
tauri::async_runtime::spawn(start_server());
|
||||
tauri::Builder::default()
|
||||
.plugin(TauriWebsocket::default())
|
||||
.run(tauri::generate_context!())
|
||||
.expect("error while running tauri application");
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
{
|
||||
"build": {
|
||||
"distDir": "../public",
|
||||
"devPath": "http://localhost:5000",
|
||||
"beforeDevCommand": "yarn dev",
|
||||
"beforeBuildCommand": "yarn build",
|
||||
"withGlobalTauri": true
|
||||
},
|
||||
"tauri": {
|
||||
"bundle": {
|
||||
"active": true,
|
||||
"targets": "all",
|
||||
"identifier": "com.tauri.dev",
|
||||
"icon": [
|
||||
"icons/32x32.png",
|
||||
"icons/128x128.png",
|
||||
"icons/128x128@2x.png",
|
||||
"icons/icon.icns",
|
||||
"icons/icon.ico"
|
||||
],
|
||||
"resources": [],
|
||||
"externalBin": [],
|
||||
"copyright": "",
|
||||
"category": "DeveloperTool",
|
||||
"shortDescription": "",
|
||||
"longDescription": "",
|
||||
"deb": {
|
||||
"depends": [],
|
||||
"useBootstrapper": false
|
||||
},
|
||||
"macOS": {
|
||||
"frameworks": [],
|
||||
"minimumSystemVersion": "",
|
||||
"useBootstrapper": false,
|
||||
"exceptionDomain": ""
|
||||
}
|
||||
},
|
||||
"allowlist": {
|
||||
"all": true
|
||||
},
|
||||
"windows": [
|
||||
{
|
||||
"title": "Tauri App",
|
||||
"width": 800,
|
||||
"height": 600,
|
||||
"resizable": true,
|
||||
"fullscreen": false
|
||||
}
|
||||
],
|
||||
"security": {
|
||||
"csp": "default-src blob: data: filesystem: ws: http: https: 'unsafe-eval' 'unsafe-inline'"
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
<script lang="ts">
|
||||
import WebSocket from 'tauri-plugin-websocket-api'
|
||||
import { onMount } from 'svelte'
|
||||
|
||||
let ws
|
||||
let response = ''
|
||||
let message = ''
|
||||
|
||||
onMount(async () => {
|
||||
ws = await WebSocket.connect('ws://127.0.0.1:8080').then(r => {
|
||||
_updateResponse('Connected')
|
||||
return r
|
||||
}).catch(_updateResponse)
|
||||
ws.addListener(_updateResponse)
|
||||
})
|
||||
|
||||
function _updateResponse(returnValue) {
|
||||
response += (typeof returnValue === 'string' ? returnValue : JSON.stringify(returnValue)) + '<br>'
|
||||
}
|
||||
|
||||
function send() {
|
||||
ws.send(message).then(() => _updateResponse('Message sent')).catch(_updateResponse)
|
||||
}
|
||||
|
||||
function disconnect() {
|
||||
ws.disconnect().then(() => _updateResponse('Disconnected')).catch(_updateResponse)
|
||||
}
|
||||
</script>
|
||||
|
||||
<div>
|
||||
<input bind:value={message}>
|
||||
<button on:click={send}>Send</button>
|
||||
<button on:click={disconnect}>Disconnect</button>
|
||||
</div>
|
||||
<div>{@html response}</div>
|
@ -0,0 +1,8 @@
|
||||
import App from './App.svelte';
|
||||
|
||||
const app = new App({
|
||||
target: document.body,
|
||||
props: {}
|
||||
});
|
||||
|
||||
export default app;
|
@ -0,0 +1,6 @@
|
||||
{
|
||||
"extends": "@tsconfig/svelte/tsconfig.json",
|
||||
|
||||
"include": ["src/**/*"],
|
||||
"exclude": ["node_modules/*", "__sapper__/*", "public/*"]
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
{
|
||||
"name": "tauri-plugin-websocket-api",
|
||||
"version": "0.1.0",
|
||||
"authors": [
|
||||
"Tauri Programme within The Commons Conservancy"
|
||||
],
|
||||
"description": "Tauri Plugin for WebSocket connections",
|
||||
"browser": "webview-dist/index.js",
|
||||
"private": "true",
|
||||
"scripts": {
|
||||
"build": "rollup -c ./webview-src/rollup.config.js",
|
||||
"prepublishOnly": "yarn build",
|
||||
"pretest": "yarn build"
|
||||
},
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"@rollup/plugin-node-resolve": "^11.1.0",
|
||||
"@rollup/plugin-typescript": "^8.1.0",
|
||||
"rollup": "^2.38.0",
|
||||
"rollup-plugin-terser": "^7.0.2",
|
||||
"typescript": "^4.1.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"@tauri-apps/api": "^1.0.0-beta.4",
|
||||
"tslib": "^2.1.0"
|
||||
}
|
||||
}
|
@ -0,0 +1,185 @@
|
||||
use futures_util::{stream::SplitSink, SinkExt, StreamExt};
|
||||
use serde::{ser::Serializer, Deserialize, Serialize};
|
||||
use serde_json::Value as JsonValue;
|
||||
use tauri::{plugin::Plugin, AppHandle, Invoke, Manager, Runtime, State, Window};
|
||||
use tokio::{net::TcpStream, sync::Mutex};
|
||||
use tokio_tungstenite::{
|
||||
connect_async_with_config,
|
||||
tungstenite::{
|
||||
protocol::{CloseFrame as ProtocolCloseFrame, WebSocketConfig},
|
||||
Message,
|
||||
},
|
||||
MaybeTlsStream, WebSocketStream,
|
||||
};
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
type Id = u32;
|
||||
type WebSocket = WebSocketStream<MaybeTlsStream<TcpStream>>;
|
||||
type WebSocketWriter = SplitSink<WebSocket, Message>;
|
||||
type Result<T> = std::result::Result<T, Error>;
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
enum Error {
|
||||
#[error(transparent)]
|
||||
Websocket(#[from] tokio_tungstenite::tungstenite::Error),
|
||||
#[error("connection not found for the given id: {0}")]
|
||||
ConnectionNotFound(Id),
|
||||
}
|
||||
|
||||
impl Serialize for Error {
|
||||
fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
serializer.serialize_str(self.to_string().as_str())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct ConnectionManager(Mutex<HashMap<Id, WebSocketWriter>>);
|
||||
|
||||
#[derive(Default, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct ConnectionConfig {
|
||||
pub max_send_queue: Option<usize>,
|
||||
pub max_message_size: Option<usize>,
|
||||
pub max_frame_size: Option<usize>,
|
||||
pub accept_unmasked_frames: bool,
|
||||
}
|
||||
|
||||
impl From<ConnectionConfig> for WebSocketConfig {
|
||||
fn from(config: ConnectionConfig) -> Self {
|
||||
Self {
|
||||
max_send_queue: config.max_send_queue,
|
||||
max_message_size: config.max_message_size,
|
||||
max_frame_size: config.max_frame_size,
|
||||
accept_unmasked_frames: config.accept_unmasked_frames,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize)]
|
||||
struct CloseFrame {
|
||||
pub code: u16,
|
||||
pub reason: String,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize)]
|
||||
#[serde(tag = "type", content = "data")]
|
||||
enum WebSocketMessage {
|
||||
Text(String),
|
||||
Binary(Vec<u8>),
|
||||
Ping(Vec<u8>),
|
||||
Pong(Vec<u8>),
|
||||
Close(Option<CloseFrame>),
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
async fn connect<R: Runtime>(
|
||||
window: Window<R>,
|
||||
manager: State<'_, ConnectionManager>,
|
||||
url: String,
|
||||
callback_function: String,
|
||||
config: Option<ConnectionConfig>,
|
||||
) -> Result<Id> {
|
||||
let (ws_stream, _) = connect_async_with_config(url, config.map(Into::into)).await?;
|
||||
let (write, read) = ws_stream.split();
|
||||
|
||||
let id = rand::random();
|
||||
manager.0.lock().await.insert(id, write);
|
||||
|
||||
tauri::async_runtime::spawn(async move {
|
||||
read.for_each(move |message| {
|
||||
let window_ = window.clone();
|
||||
let callback_function_ = callback_function.clone();
|
||||
async move {
|
||||
if let Ok(Message::Close(_)) = message {
|
||||
let manager = window_.state::<ConnectionManager>();
|
||||
manager.0.lock().await.remove(&id);
|
||||
}
|
||||
|
||||
let response = match message {
|
||||
Ok(Message::Text(t)) => {
|
||||
serde_json::to_value(WebSocketMessage::Text(t)).unwrap()
|
||||
}
|
||||
Ok(Message::Binary(t)) => {
|
||||
serde_json::to_value(WebSocketMessage::Binary(t)).unwrap()
|
||||
}
|
||||
Ok(Message::Ping(t)) => {
|
||||
serde_json::to_value(WebSocketMessage::Ping(t)).unwrap()
|
||||
}
|
||||
Ok(Message::Pong(t)) => {
|
||||
serde_json::to_value(WebSocketMessage::Pong(t)).unwrap()
|
||||
}
|
||||
Ok(Message::Close(t)) => {
|
||||
serde_json::to_value(WebSocketMessage::Close(t.map(|v| CloseFrame {
|
||||
code: v.code.into(),
|
||||
reason: v.reason.into_owned(),
|
||||
})))
|
||||
.unwrap()
|
||||
}
|
||||
Err(e) => serde_json::to_value(Error::from(e)).unwrap(),
|
||||
};
|
||||
let js = tauri::api::rpc::format_callback(callback_function_, &response)
|
||||
.expect("unable to serialize websocket message");
|
||||
let _ = window_.eval(js.as_str());
|
||||
}
|
||||
})
|
||||
.await;
|
||||
});
|
||||
|
||||
Ok(id)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
async fn send(
|
||||
manager: State<'_, ConnectionManager>,
|
||||
id: Id,
|
||||
message: WebSocketMessage,
|
||||
) -> Result<()> {
|
||||
if let Some(write) = manager.0.lock().await.get_mut(&id) {
|
||||
write
|
||||
.send(match message {
|
||||
WebSocketMessage::Text(t) => Message::Text(t),
|
||||
WebSocketMessage::Binary(t) => Message::Binary(t),
|
||||
WebSocketMessage::Ping(t) => Message::Ping(t),
|
||||
WebSocketMessage::Pong(t) => Message::Pong(t),
|
||||
WebSocketMessage::Close(t) => Message::Close(t.map(|v| ProtocolCloseFrame {
|
||||
code: v.code.into(),
|
||||
reason: std::borrow::Cow::Owned(v.reason),
|
||||
})),
|
||||
})
|
||||
.await?;
|
||||
Ok(())
|
||||
} else {
|
||||
Err(Error::ConnectionNotFound(id))
|
||||
}
|
||||
}
|
||||
|
||||
pub struct TauriWebsocket<R: Runtime> {
|
||||
invoke_handler: Box<dyn Fn(Invoke<R>) + Send + Sync>,
|
||||
}
|
||||
|
||||
impl<R: Runtime> Default for TauriWebsocket<R> {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
invoke_handler: Box::new(tauri::generate_handler![connect, send]),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: Runtime> Plugin<R> for TauriWebsocket<R> {
|
||||
fn name(&self) -> &'static str {
|
||||
"websocket"
|
||||
}
|
||||
|
||||
fn initialize(&mut self, app: &AppHandle<R>, _config: JsonValue) -> tauri::plugin::Result<()> {
|
||||
app.manage(ConnectionManager::default());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn extend_api(&mut self, invoke: Invoke<R>) {
|
||||
(self.invoke_handler)(invoke)
|
||||
}
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
export interface MessageKind<T, D> {
|
||||
type: T;
|
||||
data: D;
|
||||
}
|
||||
export interface CloseFrame {
|
||||
code: number;
|
||||
reason: string;
|
||||
}
|
||||
export declare type Message = MessageKind<'Text', string> | MessageKind<'Binary', number[]> | MessageKind<'Ping', number[]> | MessageKind<'Pong', number[]> | MessageKind<'Close', CloseFrame | null>;
|
||||
export default class WebSocket {
|
||||
id: number;
|
||||
private listeners;
|
||||
constructor(id: number, listeners: Array<(arg: Message) => void>);
|
||||
static connect(url: string, options?: any): Promise<WebSocket>;
|
||||
addListener(cb: (arg: Message) => void): void;
|
||||
send(message: Message | string | number[]): Promise<void>;
|
||||
disconnect(): Promise<void>;
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
/*! *****************************************************************************
|
||||
Copyright (c) Microsoft Corporation.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
PERFORMANCE OF THIS SOFTWARE.
|
||||
***************************************************************************** */
|
||||
function n(n,t,e,r){return new(e||(e=Promise))((function(o,i){function a(n){try{u(r.next(n))}catch(n){i(n)}}function c(n){try{u(r.throw(n))}catch(n){i(n)}}function u(n){var t;n.done?o(n.value):(t=n.value,t instanceof e?t:new e((function(n){n(t)}))).then(a,c)}u((r=r.apply(n,t||[])).next())}))}function t(n,t){var e,r,o,i,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:c(0),throw:c(1),return:c(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function c(i){return function(c){return function(i){if(e)throw new TypeError("Generator is already executing.");for(;a;)try{if(e=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return a.label++,{value:i[1],done:!1};case 5:a.label++,r=i[1],i=[0];continue;case 7:i=a.ops.pop(),a.trys.pop();continue;default:if(!(o=a.trys,(o=o.length>0&&o[o.length-1])||6!==i[0]&&2!==i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]<o[3])){a.label=i[1];break}if(6===i[0]&&a.label<o[1]){a.label=o[1],o=i;break}if(o&&a.label<o[2]){a.label=o[2],a.ops.push(i);break}o[2]&&a.ops.pop(),a.trys.pop();continue}i=t.call(n,a)}catch(n){i=[6,n],r=0}finally{e=o=0}if(5&i[0])throw i[1];return{value:i[0]?i[1]:void 0,done:!0}}([i,c])}}}
|
||||
/*! *****************************************************************************
|
||||
Copyright (c) Microsoft Corporation.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
PERFORMANCE OF THIS SOFTWARE.
|
||||
***************************************************************************** */var e=function(){return(e=Object.assign||function(n){for(var t,e=1,r=arguments.length;e<r;e++)for(var o in t=arguments[e])Object.prototype.hasOwnProperty.call(t,o)&&(n[o]=t[o]);return n}).apply(this,arguments)};function r(n,t){void 0===t&&(t=!1);var e=function(){var n=new Int8Array(1);window.crypto.getRandomValues(n);var t=new Uint8Array(Math.max(16,Math.abs(n[0])));return window.crypto.getRandomValues(t),t.join("")}();return Object.defineProperty(window,e,{value:function(r){return t&&Reflect.deleteProperty(window,e),null==n?void 0:n(r)},writable:!1,configurable:!0}),e}function o(n,t){return void 0===t&&(t={}),function(n,t,e,r){return new(e||(e=Promise))((function(o,i){function a(n){try{u(r.next(n))}catch(n){i(n)}}function c(n){try{u(r.throw(n))}catch(n){i(n)}}function u(n){var t;n.done?o(n.value):(t=n.value,t instanceof e?t:new e((function(n){n(t)}))).then(a,c)}u((r=r.apply(n,t||[])).next())}))}(this,void 0,void 0,(function(){return function(n,t){var e,r,o,i,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:c(0),throw:c(1),return:c(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function c(i){return function(c){return function(i){if(e)throw new TypeError("Generator is already executing.");for(;a;)try{if(e=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return a.label++,{value:i[1],done:!1};case 5:a.label++,r=i[1],i=[0];continue;case 7:i=a.ops.pop(),a.trys.pop();continue;default:if(!((o=(o=a.trys).length>0&&o[o.length-1])||6!==i[0]&&2!==i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]<o[3])){a.label=i[1];break}if(6===i[0]&&a.label<o[1]){a.label=o[1],o=i;break}if(o&&a.label<o[2]){a.label=o[2],a.ops.push(i);break}o[2]&&a.ops.pop(),a.trys.pop();continue}i=t.call(n,a)}catch(n){i=[6,n],r=0}finally{e=o=0}if(5&i[0])throw i[1];return{value:i[0]?i[1]:void 0,done:!0}}([i,c])}}}(this,(function(o){return[2,new Promise((function(o,i){var a=r((function(n){o(n),Reflect.deleteProperty(window,c)}),!0),c=r((function(n){i(n),Reflect.deleteProperty(window,a)}),!0);window.rpc.notify(n,e({__invokeKey:__TAURI_INVOKE_KEY__,callback:a,error:c},t))}))]}))}))}Object.freeze({__proto__:null,transformCallback:r,invoke:o,convertFileSrc:function(n){return navigator.userAgent.includes("Windows")?"https://asset.localhost/"+n:"asset://"+n}});var i=function(){function e(n,t){this.id=n,this.listeners=t}return e.connect=function(i,a){return n(this,void 0,void 0,(function(){var n;return t(this,(function(t){return n=[],[2,o("plugin:websocket|connect",{url:i,callbackFunction:r((function(t){n.forEach((function(n){return n(t)}))})),options:a}).then((function(t){return new e(t,n)}))]}))}))},e.prototype.addListener=function(n){this.listeners.push(n)},e.prototype.send=function(n){var t;if("string"==typeof n)t={type:"Text",data:n};else if("object"==typeof n&&"type"in n)t=n;else{if(!Array.isArray(n))throw new Error("invalid `message` type, expected a `{ type: string, data: any }` object, a string or a numeric array");t={type:"Binary",data:n}}return o("plugin:websocket|send",{id:this.id,message:t})},e.prototype.disconnect=function(){return this.send({type:"Close",data:{code:1e3,reason:"Disconnected by client"}})},e}();export{i as default};
|
@ -0,0 +1,71 @@
|
||||
import { invoke, transformCallback } from '@tauri-apps/api/tauri'
|
||||
|
||||
export interface MessageKind<T, D> {
|
||||
type: T
|
||||
data: D
|
||||
}
|
||||
|
||||
export interface CloseFrame {
|
||||
code: number
|
||||
reason: string
|
||||
}
|
||||
|
||||
export type Message =
|
||||
MessageKind<'Text', string> |
|
||||
MessageKind<'Binary', number[]> |
|
||||
MessageKind<'Ping', number[]> |
|
||||
MessageKind<'Pong', number[]> |
|
||||
MessageKind<'Close', CloseFrame | null>
|
||||
|
||||
export default class WebSocket {
|
||||
id: number
|
||||
private listeners: Array<(arg: Message) => void>
|
||||
|
||||
constructor(id: number, listeners: Array<(arg: Message) => void>) {
|
||||
this.id = id
|
||||
this.listeners = listeners
|
||||
}
|
||||
|
||||
static async connect(url: string, options?: any): Promise<WebSocket> {
|
||||
const listeners: Array<(arg: Message) => void> = []
|
||||
const handler = (message: Message) => {
|
||||
listeners.forEach(l => l(message))
|
||||
}
|
||||
|
||||
return invoke<number>('plugin:websocket|connect', {
|
||||
url,
|
||||
callbackFunction: transformCallback(handler),
|
||||
options
|
||||
}).then(id => new WebSocket(id, listeners))
|
||||
}
|
||||
|
||||
addListener(cb: (arg: Message) => void) {
|
||||
this.listeners.push(cb)
|
||||
}
|
||||
|
||||
send(message: Message | string | number[]): Promise<void> {
|
||||
let m: Message
|
||||
if (typeof message === 'string') {
|
||||
m = { type: 'Text', data: message }
|
||||
} else if (typeof message === 'object' && ('type' in message)) {
|
||||
m = message
|
||||
} else if (Array.isArray(message)) {
|
||||
m = { type: 'Binary', data: message }
|
||||
} else {
|
||||
throw new Error('invalid `message` type, expected a `{ type: string, data: any }` object, a string or a numeric array')
|
||||
}
|
||||
return invoke('plugin:websocket|send', {
|
||||
id: this.id,
|
||||
message: m
|
||||
})
|
||||
}
|
||||
|
||||
disconnect(): Promise<void> {
|
||||
return this.send({
|
||||
type: 'Close', data: {
|
||||
code: 1000,
|
||||
reason: 'Disconnected by client'
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
import resolve from '@rollup/plugin-node-resolve'
|
||||
import { terser } from 'rollup-plugin-terser'
|
||||
import typescript from '@rollup/plugin-typescript'
|
||||
|
||||
export default {
|
||||
input: './webview-src/index.ts',
|
||||
output: {
|
||||
dir: './webview-dist',
|
||||
entryFileNames: '[name].js',
|
||||
format: 'es',
|
||||
exports: 'auto'
|
||||
},
|
||||
plugins: [
|
||||
resolve(),
|
||||
terser(),
|
||||
typescript({
|
||||
tsconfig: './webview-src/tsconfig.json'
|
||||
})
|
||||
]
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES5",
|
||||
"strict": true,
|
||||
"allowJs": true,
|
||||
"esModuleInterop": true,
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"types": ["@types"]
|
||||
},
|
||||
"declaration": true,
|
||||
"declarationDir": "../webview-dist",
|
||||
"rootDir": "./"
|
||||
},
|
||||
"include": ["./"]
|
||||
}
|
@ -0,0 +1,296 @@
|
||||
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
|
||||
# yarn lockfile v1
|
||||
|
||||
|
||||
"@babel/code-frame@^7.10.4":
|
||||
version "7.14.5"
|
||||
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.14.5.tgz#23b08d740e83f49c5e59945fbf1b43e80bbf4edb"
|
||||
integrity sha512-9pzDqyc6OLDaqe+zbACgFkb6fKMNG6CObKpnYXChRsvYGyEdc7CA2BaqeOM+vOtCS5ndmJicPJhKAwYRI6UfFw==
|
||||
dependencies:
|
||||
"@babel/highlight" "^7.14.5"
|
||||
|
||||
"@babel/helper-validator-identifier@^7.14.5":
|
||||
version "7.14.9"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.9.tgz#6654d171b2024f6d8ee151bf2509699919131d48"
|
||||
integrity sha512-pQYxPY0UP6IHISRitNe8bsijHex4TWZXi2HwKVsjPiltzlhse2znVcm9Ace510VT1kxIHjGJCZZQBX2gJDbo0g==
|
||||
|
||||
"@babel/highlight@^7.14.5":
|
||||
version "7.14.5"
|
||||
resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.14.5.tgz#6861a52f03966405001f6aa534a01a24d99e8cd9"
|
||||
integrity sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==
|
||||
dependencies:
|
||||
"@babel/helper-validator-identifier" "^7.14.5"
|
||||
chalk "^2.0.0"
|
||||
js-tokens "^4.0.0"
|
||||
|
||||
"@rollup/plugin-node-resolve@^11.1.0":
|
||||
version "11.2.1"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/plugin-node-resolve/-/plugin-node-resolve-11.2.1.tgz#82aa59397a29cd4e13248b106e6a4a1880362a60"
|
||||
integrity sha512-yc2n43jcqVyGE2sqV5/YCmocy9ArjVAP/BeXyTtADTBBX6V0e5UMqwO8CdQ0kzjb6zu5P1qMzsScCMRvE9OlVg==
|
||||
dependencies:
|
||||
"@rollup/pluginutils" "^3.1.0"
|
||||
"@types/resolve" "1.17.1"
|
||||
builtin-modules "^3.1.0"
|
||||
deepmerge "^4.2.2"
|
||||
is-module "^1.0.0"
|
||||
resolve "^1.19.0"
|
||||
|
||||
"@rollup/plugin-typescript@^8.1.0":
|
||||
version "8.2.5"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/plugin-typescript/-/plugin-typescript-8.2.5.tgz#e0319761b2b5105615e5a0c371ae05bc2984b7de"
|
||||
integrity sha512-QL/LvDol/PAGB2O0S7/+q2HpSUNodpw7z6nGn9BfoVCPOZ0r4EALrojFU29Bkoi2Hr2jgTocTejJ5GGWZfOxbQ==
|
||||
dependencies:
|
||||
"@rollup/pluginutils" "^3.1.0"
|
||||
resolve "^1.17.0"
|
||||
|
||||
"@rollup/pluginutils@^3.1.0":
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-3.1.0.tgz#706b4524ee6dc8b103b3c995533e5ad680c02b9b"
|
||||
integrity sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==
|
||||
dependencies:
|
||||
"@types/estree" "0.0.39"
|
||||
estree-walker "^1.0.1"
|
||||
picomatch "^2.2.2"
|
||||
|
||||
"@tauri-apps/api@^1.0.0-beta.4":
|
||||
version "1.0.0-beta.8"
|
||||
resolved "https://registry.yarnpkg.com/@tauri-apps/api/-/api-1.0.0-beta.8.tgz#a43dc4a4515148f29bfb616db85445b771e84f78"
|
||||
integrity sha512-a56lXB7XvQ4+fKtT0pxpkjTSKhyrQ1Vmjyvt2ox3mT9xw3l7s8IOKHJ1WuqW6TA6xdoy3Cyja3Z3prw8hflS7g==
|
||||
|
||||
"@types/estree@0.0.39":
|
||||
version "0.0.39"
|
||||
resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f"
|
||||
integrity sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==
|
||||
|
||||
"@types/node@*":
|
||||
version "16.9.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-16.9.1.tgz#0611b37db4246c937feef529ddcc018cf8e35708"
|
||||
integrity sha512-QpLcX9ZSsq3YYUUnD3nFDY8H7wctAhQj/TFKL8Ya8v5fMm3CFXxo8zStsLAl780ltoYoo1WvKUVGBQK+1ifr7g==
|
||||
|
||||
"@types/resolve@1.17.1":
|
||||
version "1.17.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/resolve/-/resolve-1.17.1.tgz#3afd6ad8967c77e4376c598a82ddd58f46ec45d6"
|
||||
integrity sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
|
||||
ansi-styles@^3.2.1:
|
||||
version "3.2.1"
|
||||
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d"
|
||||
integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==
|
||||
dependencies:
|
||||
color-convert "^1.9.0"
|
||||
|
||||
buffer-from@^1.0.0:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5"
|
||||
integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==
|
||||
|
||||
builtin-modules@^3.1.0:
|
||||
version "3.2.0"
|
||||
resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-3.2.0.tgz#45d5db99e7ee5e6bc4f362e008bf917ab5049887"
|
||||
integrity sha512-lGzLKcioL90C7wMczpkY0n/oART3MbBa8R9OFGE1rJxoVI86u4WAGfEk8Wjv10eKSyTHVGkSo3bvBylCEtk7LA==
|
||||
|
||||
chalk@^2.0.0:
|
||||
version "2.4.2"
|
||||
resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
|
||||
integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
|
||||
dependencies:
|
||||
ansi-styles "^3.2.1"
|
||||
escape-string-regexp "^1.0.5"
|
||||
supports-color "^5.3.0"
|
||||
|
||||
color-convert@^1.9.0:
|
||||
version "1.9.3"
|
||||
resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8"
|
||||
integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==
|
||||
dependencies:
|
||||
color-name "1.1.3"
|
||||
|
||||
color-name@1.1.3:
|
||||
version "1.1.3"
|
||||
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
|
||||
integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=
|
||||
|
||||
commander@^2.20.0:
|
||||
version "2.20.3"
|
||||
resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
|
||||
integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==
|
||||
|
||||
deepmerge@^4.2.2:
|
||||
version "4.2.2"
|
||||
resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955"
|
||||
integrity sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==
|
||||
|
||||
escape-string-regexp@^1.0.5:
|
||||
version "1.0.5"
|
||||
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
|
||||
integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=
|
||||
|
||||
estree-walker@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-1.0.1.tgz#31bc5d612c96b704106b477e6dd5d8aa138cb700"
|
||||
integrity sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==
|
||||
|
||||
fsevents@~2.3.2:
|
||||
version "2.3.2"
|
||||
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a"
|
||||
integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==
|
||||
|
||||
function-bind@^1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
|
||||
integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==
|
||||
|
||||
has-flag@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
|
||||
integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0=
|
||||
|
||||
has-flag@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b"
|
||||
integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==
|
||||
|
||||
has@^1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796"
|
||||
integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==
|
||||
dependencies:
|
||||
function-bind "^1.1.1"
|
||||
|
||||
is-core-module@^2.2.0:
|
||||
version "2.6.0"
|
||||
resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.6.0.tgz#d7553b2526fe59b92ba3e40c8df757ec8a709e19"
|
||||
integrity sha512-wShG8vs60jKfPWpF2KZRaAtvt3a20OAn7+IJ6hLPECpSABLcKtFKTTI4ZtH5QcBruBHlq+WsdHWyz0BCZW7svQ==
|
||||
dependencies:
|
||||
has "^1.0.3"
|
||||
|
||||
is-module@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/is-module/-/is-module-1.0.0.tgz#3258fb69f78c14d5b815d664336b4cffb6441591"
|
||||
integrity sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE=
|
||||
|
||||
jest-worker@^26.2.1:
|
||||
version "26.6.2"
|
||||
resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-26.6.2.tgz#7f72cbc4d643c365e27b9fd775f9d0eaa9c7a8ed"
|
||||
integrity sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
merge-stream "^2.0.0"
|
||||
supports-color "^7.0.0"
|
||||
|
||||
js-tokens@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
|
||||
integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
|
||||
|
||||
merge-stream@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60"
|
||||
integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==
|
||||
|
||||
path-parse@^1.0.6:
|
||||
version "1.0.7"
|
||||
resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735"
|
||||
integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==
|
||||
|
||||
picomatch@^2.2.2:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.0.tgz#f1f061de8f6a4bf022892e2d128234fb98302972"
|
||||
integrity sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==
|
||||
|
||||
randombytes@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a"
|
||||
integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==
|
||||
dependencies:
|
||||
safe-buffer "^5.1.0"
|
||||
|
||||
resolve@^1.17.0, resolve@^1.19.0:
|
||||
version "1.20.0"
|
||||
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975"
|
||||
integrity sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==
|
||||
dependencies:
|
||||
is-core-module "^2.2.0"
|
||||
path-parse "^1.0.6"
|
||||
|
||||
rollup-plugin-terser@^7.0.2:
|
||||
version "7.0.2"
|
||||
resolved "https://registry.yarnpkg.com/rollup-plugin-terser/-/rollup-plugin-terser-7.0.2.tgz#e8fbba4869981b2dc35ae7e8a502d5c6c04d324d"
|
||||
integrity sha512-w3iIaU4OxcF52UUXiZNsNeuXIMDvFrr+ZXK6bFZ0Q60qyVfq4uLptoS4bbq3paG3x216eQllFZX7zt6TIImguQ==
|
||||
dependencies:
|
||||
"@babel/code-frame" "^7.10.4"
|
||||
jest-worker "^26.2.1"
|
||||
serialize-javascript "^4.0.0"
|
||||
terser "^5.0.0"
|
||||
|
||||
rollup@^2.38.0:
|
||||
version "2.56.3"
|
||||
resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.56.3.tgz#b63edadd9851b0d618a6d0e6af8201955a77aeff"
|
||||
integrity sha512-Au92NuznFklgQCUcV96iXlxUbHuB1vQMaH76DHl5M11TotjOHwqk9CwcrT78+Tnv4FN9uTBxq6p4EJoYkpyekg==
|
||||
optionalDependencies:
|
||||
fsevents "~2.3.2"
|
||||
|
||||
safe-buffer@^5.1.0:
|
||||
version "5.2.1"
|
||||
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
|
||||
integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
|
||||
|
||||
serialize-javascript@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-4.0.0.tgz#b525e1238489a5ecfc42afacc3fe99e666f4b1aa"
|
||||
integrity sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==
|
||||
dependencies:
|
||||
randombytes "^2.1.0"
|
||||
|
||||
source-map-support@~0.5.20:
|
||||
version "0.5.20"
|
||||
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.20.tgz#12166089f8f5e5e8c56926b377633392dd2cb6c9"
|
||||
integrity sha512-n1lZZ8Ve4ksRqizaBQgxXDgKwttHDhyfQjA6YZZn8+AroHbsIz+JjwxQDxbp+7y5OYCI8t1Yk7etjD9CRd2hIw==
|
||||
dependencies:
|
||||
buffer-from "^1.0.0"
|
||||
source-map "^0.6.0"
|
||||
|
||||
source-map@^0.6.0:
|
||||
version "0.6.1"
|
||||
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
|
||||
integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
|
||||
|
||||
source-map@~0.7.2:
|
||||
version "0.7.3"
|
||||
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383"
|
||||
integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==
|
||||
|
||||
supports-color@^5.3.0:
|
||||
version "5.5.0"
|
||||
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"
|
||||
integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==
|
||||
dependencies:
|
||||
has-flag "^3.0.0"
|
||||
|
||||
supports-color@^7.0.0:
|
||||
version "7.2.0"
|
||||
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da"
|
||||
integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==
|
||||
dependencies:
|
||||
has-flag "^4.0.0"
|
||||
|
||||
terser@^5.0.0:
|
||||
version "5.8.0"
|
||||
resolved "https://registry.yarnpkg.com/terser/-/terser-5.8.0.tgz#c6d352f91aed85cc6171ccb5e84655b77521d947"
|
||||
integrity sha512-f0JH+6yMpneYcRJN314lZrSwu9eKkUFEHLN/kNy8ceh8gaRiLgFPJqrB9HsXjhEGdv4e/ekjTOFxIlL6xlma8A==
|
||||
dependencies:
|
||||
commander "^2.20.0"
|
||||
source-map "~0.7.2"
|
||||
source-map-support "~0.5.20"
|
||||
|
||||
tslib@^2.1.0:
|
||||
version "2.3.1"
|
||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01"
|
||||
integrity sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==
|
||||
|
||||
typescript@^4.1.3:
|
||||
version "4.4.3"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.4.3.tgz#bdc5407caa2b109efd4f82fe130656f977a29324"
|
||||
integrity sha512-4xfscpisVgqqDfPaJo5vkd+Qd/ItkoagnHpufr+i2QCHBsNYp+G7UAoyFl8aPtx879u38wPV65rZ8qbGZijalA==
|