Compare commits

..

4 Commits
main ... main

Author SHA1 Message Date
Leonard Anton Gläser 498929d7b8 html pfusch 2022-03-29 13:26:29 +02:00
Leonard Anton Gläser 5c47882b19 added own_id param as statefull id for viewer 2022-03-29 10:51:48 +02:00
Leonard Anton Gläser ec4c4dcb06 asset selfhosting 2022-03-29 10:50:15 +02:00
Leonard Anton Gläser 4840394627 add some https for testing porpurses 2022-01-11 17:13:28 +01:00
49 changed files with 1605 additions and 6284 deletions

View File

@ -1,20 +1,20 @@
kind: pipeline
type: docker
name: default
steps:
- name: Publish to docker
image: plugins/docker
settings:
username:
from_secret: docker_username
password:
from_secret: docker_password
auto_tag: true
repo: docker.hibas123.de/screenshare
registry: docker.hibas123.de
debug: true
when:
branch: [main]
event:
exclude:
- pull_request
kind: pipeline
type: docker
name: default
steps:
- name: Publish to docker
image: plugins/docker
settings:
username:
from_secret: docker_username
password:
from_secret: docker_password
auto_tag: true
repo: docker.hibas123.de/screenshare
registry: docker.hibas123.de
debug: true
when:
branch: [main]
event:
exclude:
- pull_request

View File

@ -4,7 +4,7 @@ root = true
end_of_line = lf
insert_final_newline = true
[*.{js,ts,json,yml,mjs,svelte}]
[*.{js,json,yml,mjs}]
charset = utf-8
indent_style = space
indent_size = 3

View File

@ -1,36 +0,0 @@
# .github/workflows/ci.yml
name: CI
on:
push:
pull_request:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
env:
MY_DOCKER_USERNAME: ${{ secrets.MY_DOCKER_USERNAME }}
MY_DOCKER_PASSWORD: ${{ secrets.MY_DOCKER_PASSWORD }}
FORCE_COLOR: 1
steps:
- uses: https://github.com/earthly/actions-setup@v1
with:
version: v0.7.0
- uses: actions/checkout@v2
- name: Put back the git branch into git (Earthly uses it for tagging)
run: |
branch=""
if [ -n "$GITHUB_HEAD_REF" ]; then
branch="$GITHUB_HEAD_REF"
else
branch="${GITHUB_REF##*/}"
fi
git checkout -b "$branch" || true
- name: Docker Login
run: docker login git.hibas.dev --username "$MY_DOCKER_USERNAME" --password "$MY_DOCKER_PASSWORD"
- name: Earthly version
run: earthly --version
- name: Run build
run: earthly --push +docker-multi

File diff suppressed because one or more lines are too long

View File

@ -1,9 +1,3 @@
nodeLinker: node-modules
npmRegistryServer: "https://npm.hibas123.de"
plugins:
- path: .yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs
spec: "@yarnpkg/plugin-interactive-tools"
yarnPath: .yarn/releases/yarn-3.1.1.cjs
npmRegistryServer: "https://npm.hibas123.de"
nodeLinker: "node-modules"
yarnPath: .yarn/releases/yarn-3.1.1.cjs

1
Client/.gitignore vendored
View File

@ -1 +0,0 @@
dist/

View File

@ -1,18 +0,0 @@
module.exports = {
"pages": "src/pages",
"sourceDir": "public",
"routifyDir": ".routify",
"ignore": "",
"dynamicImports": true,
"singleBuild": false,
"noHashScroll": false,
"distDir": "dist",
"hashScroll": true,
"extensions": [
"html",
"svelte",
"md",
"svx"
],
"started": "2022-01-22T20:07:08.621Z"
}

View File

@ -1,41 +0,0 @@
/**
* @roxi/routify 2.18.4
* File generated Sat Jan 22 2022 21:07:08 GMT+0100 (Mitteleuropäische Normalzeit)
*/
export const __version = "2.18.4"
export const __timestamp = "2022-01-22T20:07:08.628Z"
//buildRoutes
import { buildClientTree } from "@roxi/routify/runtime/buildRoutes"
//imports
//options
export const options = {}
//tree
export const _tree = {
"name": "root",
"filepath": "/",
"root": true,
"ownMeta": {},
"absolutePath": "src/pages",
"children": [],
"isLayout": false,
"isReset": false,
"isIndex": false,
"isFallback": false,
"meta": {
"recursive": true,
"preload": false,
"prerender": true
},
"path": "/"
}
export const {tree, routes} = buildClientTree(_tree)

View File

@ -1 +0,0 @@
[]

View File

@ -1 +0,0 @@
# Client

View File

@ -1,32 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Hibas123 Screen Share</title>
<script defer type="module" src="./src/bootstrap.ts"></script>
<link id="theme" rel="stylesheet" href="/smui.css" />
<!-- <link rel="stylesheet" href="/styles.css" /> -->
<!-- Material Icons -->
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons" />
<!-- Roboto -->
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,600,700" />
<!-- Roboto Mono -->
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto+Mono" />
<style>
html,
body {
margin: 0;
}
</style>
</head>
<body></body>
</html>

View File

@ -1,64 +0,0 @@
{
"name": "@hibas123/screen-client",
"packageManager": "yarn@3.1.1",
"scripts": {
"dev": "run-p dev:routify dev:vite",
"dev:vite": "vite --host",
"dev:routify": "routify",
"build": "run-s prepare build:routify build:vite",
"build:routify": "routify -b",
"build:vite": "vite build",
"prepare": "npm run smui-theme-light && npm run smui-theme-dark",
"smui-theme-light": "smui-theme compile public/smui.css -i src/theme",
"smui-theme-dark": "smui-theme compile public/smui-dark.css -i src/theme/dark"
},
"dependencies": {
"@hibas123/utils": "^2.2.18",
"@material/theme": "^14.0.0",
"@rtdb2/sdk": "^3.0.0-beta.7",
"@smui-extra/accordion": "^7.0.0-beta.14",
"@smui-extra/badge": "^7.0.0-beta.14",
"@smui/banner": "^7.0.0-beta.14",
"@smui/button": "^7.0.0-beta.14",
"@smui/card": "^7.0.0-beta.14",
"@smui/checkbox": "^7.0.0-beta.14",
"@smui/circular-progress": "^7.0.0-beta.14",
"@smui/common": "^7.0.0-beta.14",
"@smui/data-table": "^7.0.0-beta.14",
"@smui/dialog": "^7.0.0-beta.14",
"@smui/drawer": "^7.0.0-beta.14",
"@smui/fab": "^7.0.0-beta.14",
"@smui/floating-label": "^7.0.0-beta.14",
"@smui/icon-button": "^7.0.0-beta.14",
"@smui/layout-grid": "^7.0.0-beta.14",
"@smui/line-ripple": "^7.0.0-beta.14",
"@smui/linear-progress": "^7.0.0-beta.14",
"@smui/list": "^7.0.0-beta.14",
"@smui/menu": "^7.0.0-beta.14",
"@smui/menu-surface": "^7.0.0-beta.14",
"@smui/notched-outline": "^7.0.0-beta.14",
"@smui/paper": "^7.0.0-beta.14",
"@smui/radio": "^7.0.0-beta.14",
"@smui/ripple": "^7.0.0-beta.14",
"@smui/select": "^7.0.0-beta.14",
"@smui/snackbar": "^7.0.0-beta.14",
"@smui/tab": "^7.0.0-beta.14",
"@smui/tab-indicator": "^7.0.0-beta.14",
"@smui/tab-scroller": "^7.0.0-beta.14",
"@smui/textfield": "^7.0.0-beta.14",
"@smui/top-app-bar": "^7.0.0-beta.14",
"dayjs": "^1.11.9",
"nanoid": "^3.3.6",
"peerjs": "^1.4.7",
"svelte": "^4.0.5"
},
"devDependencies": {
"@roxi/routify": "^2.18.12",
"@sveltejs/vite-plugin-svelte": "^2.4.2",
"@tsconfig/svelte": "^5.0.0",
"npm-run-all": "^4.1.5",
"smui-theme": "^7.0.0-beta.14",
"svelte-preprocess": "^5.0.4",
"vite": "^4.4.3"
}
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,5 +0,0 @@
module.exports = {
routifyDir: "src/.routify",
dynamicImports: true,
extensions: ["svelte"],
};

View File

@ -1,15 +0,0 @@
module.exports = {
"pages": "src/pages",
"sourceDir": "public",
"routifyDir": "src/.routify",
"ignore": "",
"dynamicImports": true,
"singleBuild": true,
"noHashScroll": false,
"distDir": "dist",
"hashScroll": true,
"extensions": [
"svelte"
],
"started": "2023-07-13T13:49:48.147Z"
}

View File

@ -1,57 +0,0 @@
/**
* @roxi/routify 2.18.12
* File generated Thu Jul 13 2023 15:49:48 GMT+0200 (Mitteleuropäische Sommerzeit)
*/
export const __version = "2.18.12"
export const __timestamp = "2023-07-13T13:49:48.159Z"
//buildRoutes
import { buildClientTree } from "@roxi/routify/runtime/buildRoutes"
//imports
//options
export const options = {}
//tree
export const _tree = {
"root": true,
"children": [
{
"isIndex": true,
"isPage": true,
"path": "/index",
"id": "_index",
"component": () => import('../pages/index.svelte').then(m => m.default)
},
{
"isDir": true,
"ext": "",
"children": [
{
"isDir": true,
"ext": "",
"children": [
{
"isIndex": true,
"isPage": true,
"path": "/session/:sessionid/index",
"id": "_session__sessionid_index",
"component": () => import('../pages/session/[sessionid]/index.svelte').then(m => m.default)
}
],
"path": "/session/:sessionid"
}
],
"path": "/session"
}
],
"path": "/"
}
export const {tree, routes} = buildClientTree(_tree)

View File

@ -1,3 +0,0 @@
[
"/index"
]

View File

@ -1,6 +0,0 @@
<script lang="ts">
import { Router } from "@roxi/routify";
import { routes } from "./.routify/routes";
</script>
<Router {routes} />

View File

@ -1,105 +0,0 @@
import {
type ICollectionRef,
type IDocumentRef,
UpdateTypes,
} from "@rtdb2/sdk";
import { nanoid } from "nanoid";
import { Peer } from "peerjs";
import {
collectionToStore,
Sessions,
type IMember,
type IMessage,
type ISession,
} from "./db";
import type { Readable } from "svelte/store";
import { Signal } from "@hibas123/utils";
export class Session {
#client_id = nanoid(22);
#peer: Peer;
#session: IDocumentRef<ISession>;
#members: ICollectionRef<IMember>;
#messages: ICollectionRef<IMessage>;
#self: IDocumentRef<IMember>;
#name: string;
#iv: any;
#closeSignal = new Signal();
members: Readable<(IMember & { $id: string })[]>;
messages: Readable<(IMessage & { $id: string })[]>;
get name() {
return this.#name;
}
set name(value) {
this.#name = value;
this.#self.update({ name: UpdateTypes.Value(value) });
}
constructor(id: string, name: string) {
this.#name = name;
this.#peer = new Peer(this.#client_id, {
host: window.location.hostname,
port: window.location.port as any,
path: "/peerjs",
config: {},
});
this.#session = Sessions.doc(id);
this.#members = this.#session.collection("members");
this.#messages = this.#session.collection("messages");
this.#self = this.#members.doc(this.#client_id);
this.members = collectionToStore(this.#members);
this.messages = collectionToStore(this.#messages);
this.registerSelf();
this.#iv = setInterval(() => this.tick(), 5000);
}
tick() {
this.#self.update({ lastActive: UpdateTypes.Value(Date.now()) });
}
registerSelf() {
this.#self.set({
name: this.#name,
lastActive: Date.now(),
offline: false,
});
}
close() {
this.#closeSignal.sendSignal();
clearInterval(this.#iv);
this.#self.update({ offline: UpdateTypes.Value(true) });
this.#peer.destroy();
}
}
let bitrate = new URL(window.location.href).searchParams.get("br") || 50000;
function bitrateTransform(sdp: string) {
var arr = sdp.split("\r\n");
arr.forEach((str, i) => {
if (/^a=fmtp:\d*/.test(str)) {
console.log("found fmtp");
arr[i] =
str +
`;x-google-max-bitrate=${bitrate};x-google-min-bitrate=0;x-google-start-bitrate=12000`;
} else if (/^a=mid:(1|video)/.test(str)) {
console.log("found mid");
arr[i] += "\r\nb=AS:" + bitrate;
}
});
let res = arr.join("\r\n");
console.log(sdp, res);
return res;
}

View File

@ -1,5 +0,0 @@
import App from "./App.svelte";
new App({
target: document.body,
});

View File

@ -1,43 +0,0 @@
import { AwaitStore } from "@hibas123/utils";
import Client, { type ICollectionRef } from "@rtdb2/sdk";
import { readable } from "svelte/store";
const client = new Client(
"https://rtdb.hibas123.de",
"screen_share",
"screen_share"
);
(window as any).db = client;
export const Sessions = client.collection<ISession>("sessions");
export interface ISession {}
export interface IMember {
lastActive: number;
offline: boolean;
name: string;
}
export interface IMessage {
sender: string;
message: string;
}
export function collectionToStore<T>(coll: ICollectionRef<T>) {
return readable<(T & { $id: string })[]>([], (set) => {
const cancel = new AwaitStore(false);
(async () => {
const itr = await coll.onSnapshot();
cancel.awaitValue(true).then(() => itr.close());
for await (const snapshot of itr) {
set(snapshot.docs.map((doc) => ({ ...doc.data(), $id: doc.id })));
}
})();
return () => {
cancel.send(true);
};
});
}

View File

@ -1,80 +0,0 @@
<script lang="ts">
import Button from "@smui/button";
import Textfield from "@smui/textfield";
import Paper, { Title as PTitle, Content as PContent } from "@smui/paper";
import { nanoid } from "nanoid";
import { url } from "@roxi/routify";
import Snackbar, { Actions, Label } from "@smui/snackbar";
import type { SnackbarComponentDev } from "@smui/snackbar";
import IconButton from "@smui/icon-button";
let sessionID = "";
let errorSnack: SnackbarComponentDev;
function create() {
sessionID = nanoid(22);
connect();
}
function connect() {
if (sessionID.length < 22) {
errorSnack.open();
return;
}
window.history.pushState(
undefined,
undefined,
$url(`/session/${sessionID}`)
);
sessionID = "";
}
</script>
<div class="outer">
<div class="inner">
<Paper elevation={6}>
<PContent>
<PTitle>Create Session</PTitle>
<div style="margin-top: 1rem" />
<Button variant="raised" on:click={create}>Create</Button>
</PContent>
</Paper>
<Paper elevation={6}>
<PContent>
<PTitle>Join Session</PTitle>
<Textfield
label="Session ID"
bind:value={sessionID}
style="width: 100%;"
/>
<div style="margin-top: 1rem" />
<Button variant="raised" on:click={connect}>Connect</Button>
</PContent>
</Paper>
</div>
</div>
<Snackbar bind:this={errorSnack}>
<Label>Invalid Session!</Label>
<Actions>
<IconButton class="material-icons" title="Dismiss">close</IconButton>
</Actions>
</Snackbar>
<style>
.outer {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100vh;
}
.inner {
display: grid;
grid-template-columns: repeat(2, minmax(150px, 300px));
grid-template-rows: auto;
gap: 1rem;
}
</style>

View File

@ -1,42 +0,0 @@
<script lang="ts">
import { onMount } from "svelte";
import { Session } from "../../../api";
export let sessionid: string;
let session = new Session(sessionid, "");
let members = session.members;
onMount(() => {
return () => {
session.close();
};
});
</script>
<!-- {sessionid} -->
<div class="outer">
<div class="members">
{#each $members as member (member.$id)}
<div class="member">
<div class="name">{member.name || "anon"}</div>
<div class="id">{member.$id}</div>
</div>
{/each}
</div>
<div class="content">Content</div>
</div>
<style>
.outer {
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
display: grid;
grid-template-columns: 200px 1fr;
}
</style>

View File

@ -1,28 +0,0 @@
@use "sass:color";
@use "@material/theme/color-palette";
// Svelte Colors!
@use "@material/theme/index" as theme with
(
$primary: #1e88e5,
$secondary: #d8701b,
$surface: #fff,
$background: #fff,
$error: color-palette.$red-900
);
@import "@material/typography/mdc-typography";
// html,
// body {
// background-color: theme.$surface;
// color: theme.$on-surface;
// }
// a {
// color: #40b3ff;
// }
// a:visited {
// color: color.scale(#40b3ff, $lightness: -35%);
// }

View File

@ -1,28 +0,0 @@
@use "sass:color";
@use "@material/theme/color-palette";
// Svelte Colors! (Dark Theme)
@use "@material/theme/index" as theme with
(
$primary: #1e88e5,
$secondary: #d8701b,
$surface: color.adjust(color-palette.$grey-900, $blue: +4),
$background: #000,
$error: color-palette.$red-700
);
@import "@material/typography/mdc-typography";
// html,
// body {
// background-color: #000;
// color: theme.$on-surface;
// }
// a {
// color: #40b3ff;
// }
// a:visited {
// color: color.scale(#40b3ff, $lightness: -35%);
// }

View File

@ -1,5 +0,0 @@
const autoPreprocess = require("svelte-preprocess");
module.exports = {
preprocess: autoPreprocess(),
};

View File

@ -1,20 +0,0 @@
{
"extends": "@tsconfig/svelte/tsconfig.json",
"compilerOptions": {
"target": "esnext",
"module": "esnext",
"moduleResolution": "Node",
// "resolveJsonModule": true,
"baseUrl": ".",
"outDir": "tout",
/**
* Typecheck JS in `.svelte` and `.js` files by default.
* Disable checkJs if you'd like to use dynamic types in JS.
* Note that setting allowJs false does not prevent the use
* of JS in `.svelte` files.
*/
"allowJs": true,
"checkJs": true
},
"include": ["src/**/*.d.ts", "src/**/*.ts", "src/**/*.js", "src/**/*.svelte"]
}

View File

@ -1,80 +0,0 @@
import { defineConfig } from "vite";
import { svelte } from "@sveltejs/vite-plugin-svelte";
import * as zlib from "zlib";
// https://vitejs.dev/config/
export default defineConfig({
optimizeDeps: {
exclude: ["@roxi/routify"],
},
server: {
proxy: {
"/peerjs": {
target: "http://localhost:5000/",
changeOrigin: true,
ws: true,
rewrite: (path) => path.replace(/^\/peerjs/, ""),
},
"*": "/index.html",
},
},
plugins: [svelte()],
build: {
sourcemap: false,
rollupOptions: {
plugins: [
{
name: "pregzip-files",
generateBundle: async function (options, bundle) {
let prms: Promise<any>[] = [];
for (const fileName in bundle) {
const file = bundle[fileName];
// if (fileName.startsWith("assets/")) {
let src;
if (file.type === "asset") {
src = file.source;
} else {
src = file.code;
}
// console.log("Compressing asset:", typeof file.source == "undefined" ? file : undefined)
prms.push(
new Promise<any>((yes, no) =>
zlib.gzip(
src,
{
level: 6,
},
(err, res) => (err ? no(err) : yes(res))
)
).then((gzip) => {
this.emitFile({
type: "asset",
name: file.name + ".gz",
fileName: file.fileName + ".gz",
source: gzip,
});
}),
new Promise((yes, no) =>
zlib.brotliCompress(src, (err, res) =>
err ? no(err) : yes(res)
)
).then((br) => {
this.emitFile({
type: "asset",
name: file.name + ".br",
fileName: file.fileName + ".br",
source: br as Uint8Array,
});
})
);
// }
}
await Promise.all(prms);
},
},
],
},
},
});

17
Dockerfile Normal file
View File

@ -0,0 +1,17 @@
FROM node:12
LABEL maintainer="Fabian Stamm <dev@fabianstamm.de>"
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
RUN npm config set registry https://npm.hibas123.de
COPY ["package.json", "tsconfig.json", "/usr/src/app/"]
RUN npm install
COPY src/ /usr/src/app/src
COPY public/ /usr/src/app/public
EXPOSE 3000/tcp
CMD ["npm", "run", "start"]

View File

@ -1,39 +0,0 @@
VERSION 0.7
FROM node:lts-alpine3.18
WORKDIR /build
deps:
COPY .yarnrc.yml .yarnrc.yml
COPY .yarn .yarn
COPY package.json .
COPY Server/package.json Server/
COPY Client/package.json Client/
RUN apk add --no-cache git python3 make g++ gcc
RUN yarn install
build:
FROM +deps
COPY Client ./Client
COPY Server ./Server
RUN yarn install
RUN sh -c "find . -type f -name '*.ts' | grep -v node_modules"
RUN yarn build
SAVE ARTIFACT Client/dist /dist
SAVE ARTIFACT Server/lib /lib
docker-multi:
BUILD +build
BUILD --platform linux/amd64 --platform linux/arm64 +docker
docker:
FROM +deps
COPY +build/lib ./Server/lib
COPY +build/dist ./Server/public
WORKDIR /build/Server
ENTRYPOINT ["node", "lib/index.js"]
ARG EARTHLY_TARGET_TAG
ARG TAG=$EARTHLY_TARGET_TAG
SAVE IMAGE --push git.hibas.dev/hibas123/screenshare:$TAG

1
Server/.gitignore vendored
View File

@ -1 +0,0 @@
lib/

View File

@ -1,18 +0,0 @@
{
"name": "@hibas123/screen-server",
"packageManager": "yarn@3.1.1",
"scripts": {
"start": "ts-node src/index.ts",
"build": "tsc",
"dev": "nodemon -e ts --exec ts-node src/index.ts"
},
"devDependencies": {
"@types/node": "^20.4.2",
"ts-node": "^10.9.1",
"typescript": "^5.1.6"
},
"dependencies": {
"express": "^4.18.2",
"peer": "^1.0.0"
}
}

View File

@ -1,21 +0,0 @@
import { ExpressPeerServer } from "peer";
import express = require("express");
import * as path from "path";
const app = express();
const server = app.listen(5000, () => {
console.log("Server is running on port 5000");
});
const peerServer = ExpressPeerServer(server, {
path: "/",
});
app.use("/peerjs", peerServer as any);
app.use("/", express.static("public"));
app.get('*', (req, res) => {
res.sendFile(path.resolve(__dirname, "..", "public", "index.html"));
});

View File

@ -1,13 +0,0 @@
{
"compilerOptions": {
"module": "commonjs",
"target": "esnext",
"esModuleInterop": true,
"outDir": "lib/",
"sourceMap": true,
"declaration": true,
"noImplicitAny": false
},
"exclude": ["node_modules"],
"include": ["src"]
}

25
cert/selfsigned.crt Normal file
View File

@ -0,0 +1,25 @@
-----BEGIN CERTIFICATE-----
MIIELzCCAxegAwIBAgIUD0BQwjVJXVH/a0mC5Sfjk1WQdQswDQYJKoZIhvcNAQEL
BQAwgaYxCzAJBgNVBAYTAkRFMQ4wDAYDVQQIDAVIZXNzZTEXMBUGA1UEBwwOU3Rh
ZHRhbGxlbmRvcmYxEDAOBgNVBAoMB0ZlcnJlcm8xDDAKBgNVBAsMA0lBTjEkMCIG
A1UEAwwbd2RldTEzNjEwMDAxLmZlcnJlcm9uZXQuY29tMSgwJgYJKoZIhvcNAQkB
FhlnbGFlc2xlb24xQGZlcnJlcm9uZXQuY29tMB4XDTIyMDExMTE0NTIxNFoXDTIz
MDExMTE0NTIxNFowgaYxCzAJBgNVBAYTAkRFMQ4wDAYDVQQIDAVIZXNzZTEXMBUG
A1UEBwwOU3RhZHRhbGxlbmRvcmYxEDAOBgNVBAoMB0ZlcnJlcm8xDDAKBgNVBAsM
A0lBTjEkMCIGA1UEAwwbd2RldTEzNjEwMDAxLmZlcnJlcm9uZXQuY29tMSgwJgYJ
KoZIhvcNAQkBFhlnbGFlc2xlb24xQGZlcnJlcm9uZXQuY29tMIIBIjANBgkqhkiG
9w0BAQEFAAOCAQ8AMIIBCgKCAQEAstunEBtYoA7JcsSfP+zrJOtM4Qm5sKtVohI0
wNrBenjrheYpzX5BaNhMaQHyQZ1P7TnpT0krrRxEhZ3/K2KjN1m6Zym/B0UncTSS
sEzhkSLaB6d+InIr1KPrL1XNlECfXB2CppfWnJzmh+8n7UuWgzXjYiW6A2fmIEru
0wvkscnwA4BuOhtRSNlBonaod7PyjSqrKKSAUJT3IUuL6h1vUoC2vz0xGSQdKLB9
9JtNxD+wCgiZGFVOLACeDjRc4+5aMBn48lJjl18I9rBubpbdXinJ6215w9G/YP03
ZkX2f9iizSSsveEOOtWs4cGAFTSmnNFpGPmf5AuuNb3rN5eyEwIDAQABo1MwUTAd
BgNVHQ4EFgQUOCi4I94CHUpjbiF2pUAJiwLXY8wwHwYDVR0jBBgwFoAUOCi4I94C
HUpjbiF2pUAJiwLXY8wwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOC
AQEAGVMITcIjBzEzFpBJoLQYFrhUhGcwchYlHZh/VcTf3IJAQjr0+6pHZS6LnXhk
Hn6zPgfJrm6mhdsXZahtx/mMZFGhu/coh4qXzszFiqxdqIZ9zWlNmkP4ylgVQrnD
X6kURNvGNp807aMx05dcEb//O+xUyKjiue4+CIN2y9Jst4aqB7HIC4XQJb+DwHne
UmPFjR0rhExSjntf86RuWAzlNWhQLMdyqF48rdcTqoecFLl8/vsMYWJp+IhLgUHb
3MBpxbOSUVMyYBxdV70fOkxv2LZZwO3EpM6X3id41QQXxHUrDDrlCMhCXiHFbIPR
IdwktLDNZk0gZFXdPUToNXsuTA==
-----END CERTIFICATE-----

28
cert/selfsigned.key Normal file
View File

@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCy26cQG1igDsly
xJ8/7Osk60zhCbmwq1WiEjTA2sF6eOuF5inNfkFo2ExpAfJBnU/tOelPSSutHESF
nf8rYqM3WbpnKb8HRSdxNJKwTOGRItoHp34icivUo+svVc2UQJ9cHYKml9acnOaH
7yftS5aDNeNiJboDZ+YgSu7TC+SxyfADgG46G1FI2UGidqh3s/KNKqsopIBQlPch
S4vqHW9SgLa/PTEZJB0osH30m03EP7AKCJkYVU4sAJ4ONFzj7lowGfjyUmOXXwj2
sG5ult1eKcnrbXnD0b9g/TdmRfZ/2KLNJKy94Q461azhwYAVNKac0WkY+Z/kC641
ves3l7ITAgMBAAECggEAVSX9As4CAzEG9nxk1CoWSB09HGVk4ZavzdidBLMgKQ4o
Ejbg79OLkD5pIhSrIFGkG2vWhshu4pryhCoTsLPkwBUXiMV3DB8ACATfUM9JE69j
3QEAK6Xu9+yRqpdOp6WcOF5UNLtUkHqhxVU1zOKPZSfieHc9dyGfjQAfcpnW5kxQ
aYMzPEgPP+m9jp1JyVdAEqPxV0Y8xUcaO65+yvOVJk95zZcVM9kRJpDgbVjXVl+/
0ZS4y2WXUIygEYNGcV7ZGahQZirekLEmFT1LL/c9PepAmMpur/PvOQcN+ZJvJVJ3
b377VY5ZPWLgaorEsMBQaLU+2XAxspszTGjSdrQkAQKBgQDoTRlSPKdjSBh//Tay
Km/diKhCW94BjB+X7pHopj1LWG4Ws7hJVfW/sVi9qkk8ENeOPUg2MHdmobBB1nxr
JXmmKkZD0K16BmVnGBgSatR0P57Df0wzhcBmdvcYa7ZJ7odFgcYN7sIOvB1ZJ1x0
cEbfRQ6UjudMT8BC/2W67jXMcQKBgQDFGs3Mb/gq2jarILKAnmPGbgb4uWors+Ka
QJHF+jTyqjce4zVTUvL8DtNch9DZYyKiDSx6ReDFOaylfQINqz7Kqi41q0Q//H9a
ZlAmmvn3QWcQ5mT0Xld1bWK/qbApFzZY0JF4Cys3lmH2JSqhmukLAqTV/obQRjUN
ahn4XUh4wwKBgBRINv/BH/RBJTJ3j0D7B41WEyrIDpgf/dosED051nwvml0ND/gH
M0+rUk4tAfvmlItsulNQ4/vn/hWhfnd0bCyf4Eanf5351PytU9y3yxjjPR9gi+yr
ruLDXEubi+zkkJb2/63TvMnAjudr0lywON/hjaZW28cD54tx9RXfGn9hAoGADzWH
RcwqCRx3dXL7cyNFra0VyqF8CM1DogVzeiRZa5Qo1rBPkBNpfnuiYZR1UCDvLjP4
B6NWucE+ijKAMw/Qs5C4KhoCFTHlndMhQilZOnQIgOxWQ+j3tK7xHLr6ReFtpyLI
5stt1Uc8XeL2TCwI6XmVwJF4U5/nPha+1ERWcEMCgYBoseZo3GW8LRPpzR9WvDgC
bjX2/nwG1S8r/cfyE29oRn/O/WgoFQ8uywQH5jxQKjEcNnCgIp3Jl9bdhuIPsQIO
Yi2UkwSiXNxisMUQR57q8Xcy043giaxW92WZ7R82Ysb8pBf8769TuVi/DB8EUDLG
8srPcKRNcsaUDdMSGM6yRw==
-----END PRIVATE KEY-----

784
package-lock.json generated Normal file
View File

@ -0,0 +1,784 @@
{
"name": "ScreenSharingThing",
"requires": true,
"lockfileVersion": 1,
"dependencies": {
"@cspotcode/source-map-consumer": {
"version": "0.8.0",
"resolved": "https://registry.npmjs.org/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz",
"integrity": "sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg==",
"dev": true
},
"@cspotcode/source-map-support": {
"version": "0.7.0",
"resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.7.0.tgz",
"integrity": "sha512-X4xqRHqN8ACt2aHVe51OxeA2HjbcL4MqFqXkrmQszJ1NOUuUu5u6Vqx/0lZSVNku7velL5FC/s5uEAj1lsBMhA==",
"dev": true,
"requires": {
"@cspotcode/source-map-consumer": "0.8.0"
}
},
"@tsconfig/node10": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.8.tgz",
"integrity": "sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg==",
"dev": true
},
"@tsconfig/node12": {
"version": "1.0.9",
"resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.9.tgz",
"integrity": "sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw==",
"dev": true
},
"@tsconfig/node14": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.1.tgz",
"integrity": "sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg==",
"dev": true
},
"@tsconfig/node16": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.2.tgz",
"integrity": "sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA==",
"dev": true
},
"@types/body-parser": {
"version": "1.19.2",
"resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz",
"integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==",
"requires": {
"@types/connect": "*",
"@types/node": "*"
}
},
"@types/connect": {
"version": "3.4.35",
"resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz",
"integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==",
"requires": {
"@types/node": "*"
}
},
"@types/cors": {
"version": "2.8.12",
"resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.12.tgz",
"integrity": "sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw=="
},
"@types/express": {
"version": "4.17.13",
"resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.13.tgz",
"integrity": "sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA==",
"requires": {
"@types/body-parser": "*",
"@types/express-serve-static-core": "^4.17.18",
"@types/qs": "*",
"@types/serve-static": "*"
}
},
"@types/express-serve-static-core": {
"version": "4.17.27",
"resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.27.tgz",
"integrity": "sha512-e/sVallzUTPdyOTiqi8O8pMdBBphscvI6E4JYaKlja4Lm+zh7UFSSdW5VMkRbhDtmrONqOUHOXRguPsDckzxNA==",
"requires": {
"@types/node": "*",
"@types/qs": "*",
"@types/range-parser": "*"
}
},
"@types/mime": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz",
"integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw=="
},
"@types/node": {
"version": "16.11.19",
"resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.19.tgz",
"integrity": "sha512-BPAcfDPoHlRQNKktbsbnpACGdypPFBuX4xQlsWDE7B8XXcfII+SpOLay3/qZmCLb39kV5S1RTYwXdkx2lwLYng=="
},
"@types/qs": {
"version": "6.9.7",
"resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz",
"integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw=="
},
"@types/range-parser": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz",
"integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw=="
},
"@types/serve-static": {
"version": "1.13.10",
"resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.10.tgz",
"integrity": "sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ==",
"requires": {
"@types/mime": "^1",
"@types/node": "*"
}
},
"@types/ws": {
"version": "7.4.7",
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-7.4.7.tgz",
"integrity": "sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww==",
"requires": {
"@types/node": "*"
}
},
"accepts": {
"version": "1.3.7",
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz",
"integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==",
"requires": {
"mime-types": "~2.1.24",
"negotiator": "0.6.2"
}
},
"acorn": {
"version": "8.7.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz",
"integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==",
"dev": true
},
"acorn-walk": {
"version": "8.2.0",
"resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz",
"integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==",
"dev": true
},
"ansi-regex": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="
},
"ansi-styles": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"requires": {
"color-convert": "^2.0.1"
}
},
"arg": {
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
"integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==",
"dev": true
},
"array-flatten": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
"integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI="
},
"body-parser": {
"version": "1.19.1",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.1.tgz",
"integrity": "sha512-8ljfQi5eBk8EJfECMrgqNGWPEY5jWP+1IzkzkGdFFEwFQZZyaZ21UqdaHktgiMlH0xLHqIFtE/u2OYE5dOtViA==",
"requires": {
"bytes": "3.1.1",
"content-type": "~1.0.4",
"debug": "2.6.9",
"depd": "~1.1.2",
"http-errors": "1.8.1",
"iconv-lite": "0.4.24",
"on-finished": "~2.3.0",
"qs": "6.9.6",
"raw-body": "2.4.2",
"type-is": "~1.6.18"
}
},
"bytes": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.1.tgz",
"integrity": "sha512-dWe4nWO/ruEOY7HkUJ5gFt1DCFV9zPRoJr8pV0/ASQermOZjtq8jMjOprC0Kd10GLN+l7xaUPvxzJFWtxGu8Fg=="
},
"camelcase": {
"version": "5.3.1",
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
"integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg=="
},
"cliui": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz",
"integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==",
"requires": {
"string-width": "^4.2.0",
"strip-ansi": "^6.0.0",
"wrap-ansi": "^6.2.0"
}
},
"color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"requires": {
"color-name": "~1.1.4"
}
},
"color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
},
"content-disposition": {
"version": "0.5.4",
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
"integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==",
"requires": {
"safe-buffer": "5.2.1"
}
},
"content-type": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
"integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA=="
},
"cookie": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz",
"integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA=="
},
"cookie-signature": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
"integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
},
"cors": {
"version": "2.8.5",
"resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz",
"integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==",
"requires": {
"object-assign": "^4",
"vary": "^1"
}
},
"create-require": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz",
"integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==",
"dev": true
},
"debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"requires": {
"ms": "2.0.0"
}
},
"decamelize": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
"integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA="
},
"depd": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
"integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak="
},
"destroy": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
"integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA="
},
"diff": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
"integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
"dev": true
},
"ee-first": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
"integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
},
"emoji-regex": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
},
"encodeurl": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
"integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k="
},
"escape-html": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
"integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg="
},
"etag": {
"version": "1.8.1",
"resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
"integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc="
},
"express": {
"version": "4.17.2",
"resolved": "https://registry.npmjs.org/express/-/express-4.17.2.tgz",
"integrity": "sha512-oxlxJxcQlYwqPWKVJJtvQiwHgosH/LrLSPA+H4UxpyvSS6jC5aH+5MoHFM+KABgTOt0APue4w66Ha8jCUo9QGg==",
"requires": {
"accepts": "~1.3.7",
"array-flatten": "1.1.1",
"body-parser": "1.19.1",
"content-disposition": "0.5.4",
"content-type": "~1.0.4",
"cookie": "0.4.1",
"cookie-signature": "1.0.6",
"debug": "2.6.9",
"depd": "~1.1.2",
"encodeurl": "~1.0.2",
"escape-html": "~1.0.3",
"etag": "~1.8.1",
"finalhandler": "~1.1.2",
"fresh": "0.5.2",
"merge-descriptors": "1.0.1",
"methods": "~1.1.2",
"on-finished": "~2.3.0",
"parseurl": "~1.3.3",
"path-to-regexp": "0.1.7",
"proxy-addr": "~2.0.7",
"qs": "6.9.6",
"range-parser": "~1.2.1",
"safe-buffer": "5.2.1",
"send": "0.17.2",
"serve-static": "1.14.2",
"setprototypeof": "1.2.0",
"statuses": "~1.5.0",
"type-is": "~1.6.18",
"utils-merge": "1.0.1",
"vary": "~1.1.2"
}
},
"finalhandler": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz",
"integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==",
"requires": {
"debug": "2.6.9",
"encodeurl": "~1.0.2",
"escape-html": "~1.0.3",
"on-finished": "~2.3.0",
"parseurl": "~1.3.3",
"statuses": "~1.5.0",
"unpipe": "~1.0.0"
}
},
"find-up": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
"integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
"requires": {
"locate-path": "^5.0.0",
"path-exists": "^4.0.0"
}
},
"forwarded": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
"integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow=="
},
"fresh": {
"version": "0.5.2",
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
"integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac="
},
"get-caller-file": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
"integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="
},
"http-errors": {
"version": "1.8.1",
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz",
"integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==",
"requires": {
"depd": "~1.1.2",
"inherits": "2.0.4",
"setprototypeof": "1.2.0",
"statuses": ">= 1.5.0 < 2",
"toidentifier": "1.0.1"
}
},
"iconv-lite": {
"version": "0.4.24",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
"integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
"requires": {
"safer-buffer": ">= 2.1.2 < 3"
}
},
"inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
},
"ipaddr.js": {
"version": "1.9.1",
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
"integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g=="
},
"is-fullwidth-code-point": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="
},
"locate-path": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
"integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
"requires": {
"p-locate": "^4.1.0"
}
},
"make-error": {
"version": "1.3.6",
"resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
"integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==",
"dev": true
},
"media-typer": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
"integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g="
},
"merge-descriptors": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
"integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E="
},
"methods": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
"integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4="
},
"mime": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
"integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="
},
"mime-db": {
"version": "1.51.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz",
"integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g=="
},
"mime-types": {
"version": "2.1.34",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz",
"integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==",
"requires": {
"mime-db": "1.51.0"
}
},
"ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
},
"negotiator": {
"version": "0.6.2",
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
"integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw=="
},
"object-assign": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
"integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
},
"on-finished": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
"integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=",
"requires": {
"ee-first": "1.1.1"
}
},
"p-limit": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
"integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
"requires": {
"p-try": "^2.0.0"
}
},
"p-locate": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
"integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
"requires": {
"p-limit": "^2.2.0"
}
},
"p-try": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
"integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ=="
},
"parseurl": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
"integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="
},
"path-exists": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
"integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="
},
"path-to-regexp": {
"version": "0.1.7",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
"integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w="
},
"peer": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/peer/-/peer-0.6.1.tgz",
"integrity": "sha512-zPJSPoZvo+83sPJNrW8o93QTktx7dKk67965RRDDNAIelWw1ZwE6ZmmhsvRrdNRlK0knQb3rR8GBdZlbWzCYJw==",
"requires": {
"@types/cors": "^2.8.6",
"@types/express": "^4.17.3",
"@types/ws": "^7.2.3",
"body-parser": "^1.19.0",
"cors": "^2.8.5",
"express": "^4.17.1",
"uuid": "^3.4.0",
"ws": "^7.2.3",
"yargs": "^15.3.1"
}
},
"proxy-addr": {
"version": "2.0.7",
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
"integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
"requires": {
"forwarded": "0.2.0",
"ipaddr.js": "1.9.1"
}
},
"qs": {
"version": "6.9.6",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.9.6.tgz",
"integrity": "sha512-TIRk4aqYLNoJUbd+g2lEdz5kLWIuTMRagAXxl78Q0RiVjAOugHmeKNGdd3cwo/ktpf9aL9epCfFqWDEKysUlLQ=="
},
"range-parser": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
"integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="
},
"raw-body": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.2.tgz",
"integrity": "sha512-RPMAFUJP19WIet/99ngh6Iv8fzAbqum4Li7AD6DtGaW2RpMB/11xDoalPiJMTbu6I3hkbMVkATvZrqb9EEqeeQ==",
"requires": {
"bytes": "3.1.1",
"http-errors": "1.8.1",
"iconv-lite": "0.4.24",
"unpipe": "1.0.0"
}
},
"require-directory": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
"integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I="
},
"require-main-filename": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
"integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg=="
},
"safe-buffer": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
},
"safer-buffer": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
},
"send": {
"version": "0.17.2",
"resolved": "https://registry.npmjs.org/send/-/send-0.17.2.tgz",
"integrity": "sha512-UJYB6wFSJE3G00nEivR5rgWp8c2xXvJ3OPWPhmuteU0IKj8nKbG3DrjiOmLwpnHGYWAVwA69zmTm++YG0Hmwww==",
"requires": {
"debug": "2.6.9",
"depd": "~1.1.2",
"destroy": "~1.0.4",
"encodeurl": "~1.0.2",
"escape-html": "~1.0.3",
"etag": "~1.8.1",
"fresh": "0.5.2",
"http-errors": "1.8.1",
"mime": "1.6.0",
"ms": "2.1.3",
"on-finished": "~2.3.0",
"range-parser": "~1.2.1",
"statuses": "~1.5.0"
},
"dependencies": {
"ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
}
}
},
"serve-static": {
"version": "1.14.2",
"resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.2.tgz",
"integrity": "sha512-+TMNA9AFxUEGuC0z2mevogSnn9MXKb4fa7ngeRMJaaGv8vTwnIEkKi+QGvPt33HSnf8pRS+WGM0EbMtCJLKMBQ==",
"requires": {
"encodeurl": "~1.0.2",
"escape-html": "~1.0.3",
"parseurl": "~1.3.3",
"send": "0.17.2"
}
},
"set-blocking": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
"integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc="
},
"setprototypeof": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
"integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="
},
"statuses": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
"integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow="
},
"string-width": {
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
"requires": {
"emoji-regex": "^8.0.0",
"is-fullwidth-code-point": "^3.0.0",
"strip-ansi": "^6.0.1"
}
},
"strip-ansi": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
"requires": {
"ansi-regex": "^5.0.1"
}
},
"toidentifier": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
"integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA=="
},
"ts-node": {
"version": "10.4.0",
"resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.4.0.tgz",
"integrity": "sha512-g0FlPvvCXSIO1JDF6S232P5jPYqBkRL9qly81ZgAOSU7rwI0stphCgd2kLiCrU9DjQCrJMWEqcNSjQL02s6d8A==",
"dev": true,
"requires": {
"@cspotcode/source-map-support": "0.7.0",
"@tsconfig/node10": "^1.0.7",
"@tsconfig/node12": "^1.0.7",
"@tsconfig/node14": "^1.0.0",
"@tsconfig/node16": "^1.0.2",
"acorn": "^8.4.1",
"acorn-walk": "^8.1.1",
"arg": "^4.1.0",
"create-require": "^1.1.0",
"diff": "^4.0.1",
"make-error": "^1.1.1",
"yn": "3.1.1"
}
},
"type-is": {
"version": "1.6.18",
"resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
"integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
"requires": {
"media-typer": "0.3.0",
"mime-types": "~2.1.24"
}
},
"typescript": {
"version": "4.5.4",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.4.tgz",
"integrity": "sha512-VgYs2A2QIRuGphtzFV7aQJduJ2gyfTljngLzjpfW9FoYZF6xuw1W0vW9ghCKLfcWrCFxK81CSGRAvS1pn4fIUg==",
"dev": true
},
"unpipe": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
"integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw="
},
"utils-merge": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
"integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM="
},
"uuid": {
"version": "3.4.0",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A=="
},
"vary": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
"integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw="
},
"which-module": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz",
"integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho="
},
"wrap-ansi": {
"version": "6.2.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
"integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
"requires": {
"ansi-styles": "^4.0.0",
"string-width": "^4.1.0",
"strip-ansi": "^6.0.0"
}
},
"ws": {
"version": "7.5.6",
"resolved": "https://registry.npmjs.org/ws/-/ws-7.5.6.tgz",
"integrity": "sha512-6GLgCqo2cy2A2rjCNFlxQS6ZljG/coZfZXclldI8FB/1G3CCI36Zd8xy2HrFVACi8tfk5XrgLQEk+P0Tnz9UcA=="
},
"y18n": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz",
"integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ=="
},
"yargs": {
"version": "15.4.1",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz",
"integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==",
"requires": {
"cliui": "^6.0.0",
"decamelize": "^1.2.0",
"find-up": "^4.1.0",
"get-caller-file": "^2.0.1",
"require-directory": "^2.1.1",
"require-main-filename": "^2.0.0",
"set-blocking": "^2.0.0",
"string-width": "^4.2.0",
"which-module": "^2.0.0",
"y18n": "^4.0.0",
"yargs-parser": "^18.1.2"
}
},
"yargs-parser": {
"version": "18.1.3",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz",
"integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==",
"requires": {
"camelcase": "^5.0.0",
"decamelize": "^1.2.0"
}
},
"yn": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
"integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==",
"dev": true
}
}
}

View File

@ -1,24 +1,16 @@
{
"name": "ScreenSharingThing",
"packageManager": "yarn@3.1.1",
"version": "0.1.0",
"private": true,
"scripts": {
"build:client": "yarn workspace @hibas123/screen-client build",
"build:server": "yarn workspace @hibas123/screen-server build",
"build": "run-s build:server build:client",
"dev:client": "yarn workspace @hibas123/screen-client dev",
"dev:server": "yarn workspace @hibas123/screen-server dev",
"dev": "run-p dev:client dev:server"
},
"workspaces": [
"Server",
"Client"
],
"devDependencies": {
"npm-run-all": "^4.1.5"
},
"dependencies": {
"@hibas123/jrpcgen": "~1.2.13"
}
}
"name": "ScreenSharingThing",
"packageManager": "yarn@3.1.1",
"scripts": {
"start": "ts-node src/index.ts"
},
"devDependencies": {
"@types/node": "^16.11.11",
"ts-node": "^10.4.0",
"typescript": "^4.5.2"
},
"dependencies": {
"express": "^4.17.1",
"peer": "^0.6.1"
}
}

7
public/css/bootstrap.min.css vendored Normal file

File diff suppressed because one or more lines are too long

24
public/css/mystyle.css Normal file
View File

@ -0,0 +1,24 @@
/* * {
box-sizing: border-box !important;
margin: 0 !important;
padding: 0 !important;
} */
/* #main {
position: fixed;
top: 0px;
bottom: 0px;
left: 0px;
right: 0px;
}
*/
body {
margin: 0;
height: 100vh;
width: 100%;
/* overflow: hidden; */
}
video {
width: 100% !important;
height: auto !important;
background-color: black;
}

43
public/index.html Normal file
View File

@ -0,0 +1,43 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, height= initial-scale=1.0">
<link rel="stylesheet" href="./css/mystyle.css">
<title>SimpleStream</title>
<!-- //asset self hosting for non internet environments
//TODO: improve this later with correct tools like bundeling
-->
<link href="./css/bootstrap.min.css" rel="stylesheet">
<script src="./lib/jquery.min.js"></script>
<script src="./lib/bootstrap.bundle.min.js"></script>
<script src="./lib/peerjs.min.js"></script>
</head>
<body>
<div class="container-fluid vh-100">
<div class="row-fluid">
<div class="col-md-auto">
<h1>SimpleStream (Alpha)</h1>
<h2>Your ID: <span id="streamId"></span></h2>
<div id="streamURLCont">
<h2>Connect URL: <a id="streamURL"></a></h2>
</div>
<div id="connectToCont">
<h2>Connecting to: <span id="connectToID"></span></h2>
<button id="startStramBTN">Start Stream</button>
</div>
</div>
<video id="localVideo" autoplay muted></video>
</div>
</div>
<!-- style="min-width: 100%; min-height: 100%;width: auto; height: auto; z-index: -100; background-color: black;" -->
<script src="main.mjs" type="module">
</script>
</body>
</html>

7
public/lib/bootstrap.bundle.min.js vendored Normal file

File diff suppressed because one or more lines are too long

2
public/lib/jquery.min.js vendored Normal file

File diff suppressed because one or more lines are too long

70
public/lib/peerjs.min.js vendored Normal file

File diff suppressed because one or more lines are too long

202
public/main.mjs Normal file
View File

@ -0,0 +1,202 @@
function simpleFramwork() {
let obj = {};
return new Proxy(obj, {
get(_, prop) {
const [id, param] = prop.split("_");
let elm = document.getElementById(id);
if (!elm) {
console.log(`Element with id ${id} not found`);
return false;
}
switch (param) {
case "value":
return elm.value;
case "href":
return elm.href;
case "style":
return elm.getAttribute("style");
case "text":
return elm.innerText;
case undefined:
return elm;
}
},
set(_, prop, value) {
const [id, param] = prop.split("_");
let elm = document.getElementById(id);
if (!elm) {
console.log(`Element with id ${id} not found`);
return false;
}
switch (param) {
case "value":
elm.value = value;
break;
case "href":
elm.href = value;
break;
case "click":
elm.addEventListener("click", value);
break;
case "style":
elm.setAttribute("style", value);
break;
case "text":
elm.innerText = value;
break;
case undefined:
break;
}
return true;
},
});
}
let sf = simpleFramwork();
sf.streamId_text = "Loading...";
sf.streamURL_text = "Loading...";
sf.localVideo.enableAutosize = true;
let connectToId = new URL(window.location.href).searchParams.get("id");
let ownId = new URL(window.location.href).searchParams.get("own_id");
let autoFullscreen = new URL(window.location.href).searchParams.get("auto_fullscreen");
let bitrate = new URL(window.location.href).searchParams.get("br") || 50000;
//Connect to ID means: Iam the screensharer now.
//no ID Specified = Iam the Viewer
if (connectToId) {
sf.streamURLCont_style = "display:none";
sf.connectToCont_style = "display:block";
sf.connectToID_text = connectToId;
} else {
sf.streamURLCont_style = "display:block";
sf.connectToCont_style = "display:none";
}
if (ownId) {
var peer = new Peer(ownId, {
host: window.location.hostname,
port: window.location.port,
path: "/peerjs",
});
} else {
var peer = new Peer({
host: window.location.hostname,
port: window.location.port,
path: "/peerjs",
});
}
function fullscreenHandler(element, fullscreensetting) {
//main.mjs: 98 Failed to execute 'requestFullscreen' on 'Element': API can only be initiated by a user gesture.
//if (fullscreensetting) {
let res = element.requestFullscreen();
console.log(res);
//}
}
function bitrateTransform(sdp) {
var arr = sdp.split("\r\n");
arr.forEach((str, i) => {
if (/^a=fmtp:\d*/.test(str)) {
console.log("found fmtp");
arr[i] =
str +
`;x-google-max-bitrate=${bitrate};x-google-min-bitrate=0;x-google-start-bitrate=12000`;
} else if (/^a=mid:(1|video)/.test(str)) {
console.log("found mid");
arr[i] += "\r\nb=AS:" + bitrate;
}
});
let res = arr.join("\r\n");
console.log(sdp, res);
return res;
}
let currentStream = undefined;
peer.on("open", (id) => {
console.log("ID", id);
sf.streamId_text = id;
//clearing the params from the url
let url = new URL(window.location.href.split('?')[0]);
url.searchParams.set("id", id);
sf.streamURL_text = url.href;
sf.streamURL_href = url.href;
let con = peer.connect(connectToId);
con.on("data", console.log);
con.on("open", () => con.send("Hello"));
if (connectToId) {
sf.startStramBTN_click = () => {
navigator.mediaDevices
.getDisplayMedia({
video: true,
})
.then((stream) => {
if (currentStream) {
currentStream.getTracks().forEach(track => track.stop())
}
currentStream = stream;
let v = sf.localVideo;
v.srcObject = stream;
v.play();
const conn = peer.call(connectToId, stream, {
sdpTransform: bitrateTransform,
});
conn.on("stream", console.log);
conn.on("close", console.log);
conn.on("error", console.log);
});
};
}
});
peer.on("connection", (conn) => {
console.log("connection", conn);
conn.on("data", console.log);
});
peer.on("error", console.error);
peer.on("close", console.log);
peer.on("disconnected", console.log);
peer.on("error", console.log);
peer.on("call", (call) => {
console.log("Call", call);
call.answer(undefined);
call.on("stream", console.log);
call.on("close", console.log);
call.on("error", console.log);
call.on("stream", (remoteStream) => {
console.log("stream", remoteStream);
let v = sf.localVideo;
v.srcObject = remoteStream;
//fullscreenHandler(v, autoFullscreen);
v.muted = true;
v.autoplay = true;
//because of https://developer.mozilla.org/de/docs/Web/HTML/Element/video
//because of https://developer.chrome.com/blog/autoplay/ (autoplay / play not possible with sound enabled)
v.play();
});
});
function createEmptyVideoTrack({ width, height }) {
const canvas = Object.assign(document.createElement("canvas"), {
width,
height,
});
canvas.getContext("2d").fillRect(0, 0, width, height);
const stream = canvas.captureStream();
const track = stream.getVideoTracks()[0];
return Object.assign(track, { enabled: false });
}

23
src/index.ts Normal file
View File

@ -0,0 +1,23 @@
import { ExpressPeerServer } from "peer";
import * as express from "express";
import * as fs from "fs";
import * as https from "https";
import * as path from "path";
const cert = fs.readFileSync(path.resolve(__dirname, "../cert/selfsigned.crt"), 'utf8');
const key = fs.readFileSync(path.resolve(__dirname, "../cert/selfsigned.key"), 'utf8');
var credentials = { key: key, cert: cert };
const app = express();
const https_server = https.createServer(credentials,app)
let server = https_server.listen(8001);
const peerServer = ExpressPeerServer(server, {
path: "/",
});
console.log("Started server!")
app.use("/peerjs", peerServer as any);
app.use("/", express.static("public"));

10
tsconfig.json Normal file
View File

@ -0,0 +1,10 @@
{
"compilerOptions": {
"target": "es2016" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */,
"module": "commonjs" /* Specify what module code is generated. */,
"moduleResolution": "node" /* Specify how the compiler resolves module names. */,
"esModuleInterop": false /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility. */,
"forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */,
"skipLibCheck": true /* Skip type checking all .d.ts files. */
}
}

5326
yarn.lock

File diff suppressed because it is too large Load Diff