Merge branch 'release-1.0'
@@ -1,7 +0,0 @@
|
|||||||
# ~/.bash_logout: executed by bash(1) when login shell exits.
|
|
||||||
|
|
||||||
# when leaving the console clear the screen to increase privacy
|
|
||||||
|
|
||||||
if [ "$SHLVL" = 1 ]; then
|
|
||||||
[ -x /usr/bin/clear_console ] && /usr/bin/clear_console -q
|
|
||||||
fi
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
{"Key":"unix:///var/run/docker.sock","Name":"","Global":false}
|
|
||||||
48
.github/workflows/docker-image.yml
vendored
@@ -1,4 +1,5 @@
|
|||||||
name: Build and Push Docker Image
|
name: Build and Push Docker Image
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
@@ -8,7 +9,7 @@ on:
|
|||||||
tag_name:
|
tag_name:
|
||||||
description: "Custom tag name for the Docker image"
|
description: "Custom tag name for the Docker image"
|
||||||
required: false
|
required: false
|
||||||
default: "development-latest"
|
default: ""
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
@@ -16,49 +17,64 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
uses: actions/setup-node@v2
|
uses: actions/setup-node@v2
|
||||||
with:
|
with:
|
||||||
node-version: '18'
|
node-version: '18'
|
||||||
|
|
||||||
- name: Install Dependencies and Build Frontend
|
- name: Install Dependencies and Build Frontend
|
||||||
run: |
|
run: |
|
||||||
cd frontend
|
cd frontend
|
||||||
npm install
|
npm ci
|
||||||
npm run build
|
npm run build
|
||||||
|
|
||||||
- name: Setup Docker Buildx
|
- name: Setup Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v1
|
uses: docker/setup-buildx-action@v1
|
||||||
|
|
||||||
- name: Set up QEMU
|
- name: Set up QEMU
|
||||||
uses: docker/setup-qemu-action@v1
|
uses: docker/setup-qemu-action@v1
|
||||||
|
|
||||||
- name: Login to Docker Registry
|
- name: Login to Docker Registry
|
||||||
uses: docker/login-action@v1
|
uses: docker/login-action@v1
|
||||||
with:
|
with:
|
||||||
registry: ghcr.io
|
registry: ghcr.io
|
||||||
username: ${{ github.actor }}
|
username: ${{ github.actor }}
|
||||||
password: ${{ secrets.GITHUB_TOKEN }}
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
- name: Determine Docker image tag
|
- name: Determine Docker image tag
|
||||||
run: |
|
run: |
|
||||||
echo "REPO_OWNER=$(echo ${{ github.repository_owner }} | tr '[:upper:]' '[:lower:]')" >> $GITHUB_ENV
|
echo "REPO_OWNER=$(echo ${{ github.repository_owner }} | tr '[:upper:]' '[:lower:]')" >> $GITHUB_ENV
|
||||||
if [ -n "${{ github.event.inputs.tag_name }}" ]; then
|
if [ "${{ github.event.inputs.tag_name }}" == "" ]; then
|
||||||
IMAGE_TAG="${{ github.event.inputs.tag_name }}"
|
IMAGE_TAG="${{ github.ref_name }}-development-latest"
|
||||||
else
|
else
|
||||||
IMAGE_TAG="development-latest"
|
IMAGE_TAG="${{ github.event.inputs.tag_name }}"
|
||||||
fi
|
fi
|
||||||
echo "IMAGE_TAG=$IMAGE_TAG" >> $GITHUB_ENV
|
echo "IMAGE_TAG=$IMAGE_TAG" >> $GITHUB_ENV
|
||||||
|
|
||||||
- name: Build and Push Docker Image
|
- name: Build and Push Docker Image
|
||||||
uses: docker/build-push-action@v2
|
uses: docker/build-push-action@v2
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
file: ./docker/Dockerfile
|
file: ./docker/Dockerfile
|
||||||
push: true
|
push: true
|
||||||
tags: ghcr.io/${{ env.REPO_OWNER }}/ssh-project:${{ env.IMAGE_TAG }}
|
tags: ghcr.io/${{ env.REPO_OWNER }}/termix:${{ env.IMAGE_TAG }}
|
||||||
labels: org.opencontainers.image.source=https://github.com/${{ github.repository }}
|
labels: org.opencontainers.image.source=https://github.com/${{ github.repository }}
|
||||||
|
|
||||||
- name: Cleanup Docker Images
|
- name: Notify via ntfy
|
||||||
run: docker image prune -af
|
run: |
|
||||||
|
curl -d "Docker image build and push completed successfully for tag: ${{ env.IMAGE_TAG }}" \
|
||||||
|
https://ntfy.karmaashomepage.online/termix-build
|
||||||
|
|
||||||
|
- name: Delete all untagged image versions
|
||||||
|
uses: quartx-analytics/ghcr-cleaner@v1
|
||||||
|
with:
|
||||||
|
owner-type: user
|
||||||
|
token: ${{ secrets.GHCR_TOKEN }}
|
||||||
|
repository-owner: ${{ github.repository_owner }}
|
||||||
|
delete-untagged: true
|
||||||
|
|
||||||
|
- name: Cleanup Docker Images Locally
|
||||||
|
run: |
|
||||||
|
docker image prune -af
|
||||||
|
docker system prune -af --volumes
|
||||||
2
.gitignore
vendored
@@ -133,6 +133,8 @@ yarn-error.log*
|
|||||||
.sudo_as_admin_successful
|
.sudo_as_admin_successful
|
||||||
.wget-hsts
|
.wget-hsts
|
||||||
.git-credentials
|
.git-credentials
|
||||||
|
.docker/
|
||||||
|
.bash_logout
|
||||||
|
|
||||||
# VSCode Files
|
# VSCode Files
|
||||||
.vscode-server/
|
.vscode-server/
|
||||||
|
|||||||
1
.idea/.name
generated
Normal file
@@ -0,0 +1 @@
|
|||||||
|
Termix
|
||||||
12
.idea/Termix.iml
generated
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module type="WEB_MODULE" version="4">
|
||||||
|
<component name="NewModuleRootManager">
|
||||||
|
<content url="file://$MODULE_DIR$">
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/.tmp" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/temp" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/tmp" />
|
||||||
|
</content>
|
||||||
|
<orderEntry type="inheritedJdk" />
|
||||||
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
</component>
|
||||||
|
</module>
|
||||||
1
.idea/icon.svg
generated
Normal file
|
After Width: | Height: | Size: 47 KiB |
2
.idea/modules.xml
generated
@@ -2,7 +2,7 @@
|
|||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="ProjectModuleManager">
|
<component name="ProjectModuleManager">
|
||||||
<modules>
|
<modules>
|
||||||
<module fileurl="file://$PROJECT_DIR$/.idea/SSH-Project-JB.iml" filepath="$PROJECT_DIR$/.idea/SSH-Project-JB.iml" />
|
<module fileurl="file://$PROJECT_DIR$/.idea/Termix.iml" filepath="$PROJECT_DIR$/.idea/Termix.iml" />
|
||||||
</modules>
|
</modules>
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
||||||
2
.idea/vcs.xml
generated
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="VcsDirectoryMappings">
|
<component name="VcsDirectoryMappings">
|
||||||
<mapping directory="" vcs="Git" />
|
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
||||||
467
.idea/workspace.xml
generated
Normal file
@@ -0,0 +1,467 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="AutoImportSettings">
|
||||||
|
<option name="autoReloadType" value="SELECTIVE" />
|
||||||
|
</component>
|
||||||
|
<component name="ChangeListManager">
|
||||||
|
<list default="true" id="8497df64-d86b-4c98-ac58-c157d9d3fb1e" name="Changes" comment="Fix timeout on close.">
|
||||||
|
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/frontend/src/App.jsx" beforeDir="false" afterPath="$PROJECT_DIR$/frontend/src/App.jsx" afterDir="false" />
|
||||||
|
</list>
|
||||||
|
<option name="SHOW_DIALOG" value="false" />
|
||||||
|
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||||
|
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
|
||||||
|
<option name="LAST_RESOLUTION" value="IGNORE" />
|
||||||
|
</component>
|
||||||
|
<component name="Git.Settings">
|
||||||
|
<option name="RECENT_BRANCH_BY_REPOSITORY">
|
||||||
|
<map>
|
||||||
|
<entry key="$PROJECT_DIR$" value="release-1.0" />
|
||||||
|
</map>
|
||||||
|
</option>
|
||||||
|
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
|
||||||
|
</component>
|
||||||
|
<component name="GitHubPullRequestSearchHistory">{
|
||||||
|
"lastFilter": {}
|
||||||
|
}</component>
|
||||||
|
<component name="GithubPullRequestsUISettings">{
|
||||||
|
"selectedUrlAndAccountId": {
|
||||||
|
"url": "https://github.com/LukeGus/Termix",
|
||||||
|
"accountId": "f107d505-1915-4c73-a3f4-e0440737e1dc"
|
||||||
|
}
|
||||||
|
}</component>
|
||||||
|
<component name="ProjectColorInfo">{
|
||||||
|
"customColor": "636378de",
|
||||||
|
"associatedIndex": 8
|
||||||
|
}</component>
|
||||||
|
<component name="ProjectId" id="2pojjnjB8kTL4lo1P2No1yvZp4c" />
|
||||||
|
<component name="ProjectLevelVcsManager" settingsEditedManually="true">
|
||||||
|
<ConfirmationsSetting value="1" id="Add" />
|
||||||
|
</component>
|
||||||
|
<component name="ProjectViewState">
|
||||||
|
<option name="hideEmptyMiddlePackages" value="true" />
|
||||||
|
<option name="showLibraryContents" value="true" />
|
||||||
|
</component>
|
||||||
|
<component name="PropertiesComponent">{
|
||||||
|
"keyToString": {
|
||||||
|
"ASKED_SHARE_PROJECT_CONFIGURATION_FILES": "true",
|
||||||
|
"RunOnceActivity.ShowReadmeOnStart": "true",
|
||||||
|
"RunOnceActivity.git.unshallow": "true",
|
||||||
|
"Shell Script.Node Server.js Start.executor": "Run",
|
||||||
|
"Shell Script.Run backend and frontend.executor": "Run",
|
||||||
|
"Shell Script.run_backend_frontend.executor": "Run",
|
||||||
|
"git-widget-placeholder": "release-1.0",
|
||||||
|
"ignore.virus.scanning.warn.message": "true",
|
||||||
|
"last_opened_file_path": "C:/Users/Luke/Documents/Personal Projects/Termix/frontend",
|
||||||
|
"node.js.detected.package.eslint": "true",
|
||||||
|
"node.js.detected.package.tslint": "true",
|
||||||
|
"node.js.selected.package.eslint": "(autodetect)",
|
||||||
|
"node.js.selected.package.tslint": "(autodetect)",
|
||||||
|
"nodejs_package_manager_path": "npm",
|
||||||
|
"npm.run_start.executor": "Run",
|
||||||
|
"npm.run_start_frontend.executor": "Run",
|
||||||
|
"npm.run_start_node_backend.executor": "Run",
|
||||||
|
"npm.run_start_vite.executor": "Run",
|
||||||
|
"npm.start.executor": "Run",
|
||||||
|
"settings.editor.selected.configurable": "ml.llm.LLMConfigurable",
|
||||||
|
"ts.external.directory.path": "D:\\Program Files (x86)\\Applications\\Jetbrains Webstorm\\WebStorm 2024.3.1\\plugins\\javascript-plugin\\jsLanguageServicesImpl\\external",
|
||||||
|
"vue.rearranger.settings.migration": "true"
|
||||||
|
}
|
||||||
|
}</component>
|
||||||
|
<component name="RecentsManager">
|
||||||
|
<key name="CopyFile.RECENT_KEYS">
|
||||||
|
<recent name="C:\Users\Luke\Documents\Personal Projects\Termix\frontend" />
|
||||||
|
<recent name="C:\Users\Luke\Documents\Personal Projects\Termix" />
|
||||||
|
</key>
|
||||||
|
<key name="MoveFile.RECENT_KEYS">
|
||||||
|
<recent name="C:\Users\Luke\Documents\Personal Projects\Termix\frontend\src" />
|
||||||
|
<recent name="D:\Programming Projects\Termix\repo-images" />
|
||||||
|
<recent name="D:\Programming Projects\SSH-Project-JB\public" />
|
||||||
|
</key>
|
||||||
|
</component>
|
||||||
|
<component name="RunManager" selected="Shell Script.run_backend_frontend">
|
||||||
|
<configuration name="run_backend_frontend" type="ShConfigurationType">
|
||||||
|
<option name="SCRIPT_TEXT" value="Start-Process "powershell" -ArgumentList "-NoProfile", "-Command npm run start-vite"; Start-Process "powershell" -ArgumentList "-NoProfile", "-Command npm run start-server" " />
|
||||||
|
<option name="INDEPENDENT_SCRIPT_PATH" value="false" />
|
||||||
|
<option name="SCRIPT_PATH" value="$PROJECT_DIR$/../../../../../Windows/System32/WindowsPowerShell/v1.0/powershell.exe" />
|
||||||
|
<option name="SCRIPT_OPTIONS" value="" />
|
||||||
|
<option name="INDEPENDENT_SCRIPT_WORKING_DIRECTORY" value="false" />
|
||||||
|
<option name="SCRIPT_WORKING_DIRECTORY" value="$PROJECT_DIR$/frontend" />
|
||||||
|
<option name="INDEPENDENT_INTERPRETER_PATH" value="false" />
|
||||||
|
<option name="INTERPRETER_PATH" value="$PROJECT_DIR$/../../../../../Windows/System32/WindowsPowerShell/v1.0/powershell.exe" />
|
||||||
|
<option name="INTERPRETER_OPTIONS" value="" />
|
||||||
|
<option name="EXECUTE_IN_TERMINAL" value="false" />
|
||||||
|
<option name="EXECUTE_SCRIPT_FILE" value="false" />
|
||||||
|
<envs />
|
||||||
|
<method v="2" />
|
||||||
|
</configuration>
|
||||||
|
<configuration name="run_start_frontend" type="js.build_tools.npm">
|
||||||
|
<package-json value="$PROJECT_DIR$/frontend/package.json" />
|
||||||
|
<command value="start" />
|
||||||
|
<node-interpreter value="project" />
|
||||||
|
<envs />
|
||||||
|
<EXTENSION ID="com.intellij.lang.javascript.buildTools.npm.rc.StartBrowserRunConfigurationExtension">
|
||||||
|
<browser name="a7bb68e0-33c0-4d6f-a81a-aac1fdb870c8" start="true" url="http://localhost:8080" />
|
||||||
|
</EXTENSION>
|
||||||
|
<method v="2" />
|
||||||
|
</configuration>
|
||||||
|
<list>
|
||||||
|
<item itemvalue="Shell Script.run_backend_frontend" />
|
||||||
|
<item itemvalue="npm.run_start_frontend" />
|
||||||
|
</list>
|
||||||
|
</component>
|
||||||
|
<component name="SharedIndexes">
|
||||||
|
<attachedChunks>
|
||||||
|
<set>
|
||||||
|
<option value="bundled-js-predefined-d6986cc7102b-deb605915726-JavaScript-WS-243.22562.112" />
|
||||||
|
</set>
|
||||||
|
</attachedChunks>
|
||||||
|
</component>
|
||||||
|
<component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level" UseSingleDictionary="true" transferred="true" />
|
||||||
|
<component name="TaskManager">
|
||||||
|
<task active="true" id="Default" summary="Default task">
|
||||||
|
<changelist id="8497df64-d86b-4c98-ac58-c157d9d3fb1e" name="Changes" comment="" />
|
||||||
|
<created>1733439468142</created>
|
||||||
|
<option name="number" value="Default" />
|
||||||
|
<option name="presentableId" value="Default" />
|
||||||
|
<updated>1733439468142</updated>
|
||||||
|
<workItem from="1733439479708" duration="5489000" />
|
||||||
|
<workItem from="1733448523969" duration="3535000" />
|
||||||
|
<workItem from="1733549186397" duration="8748000" />
|
||||||
|
<workItem from="1733599078854" duration="1895000" />
|
||||||
|
<workItem from="1733601633451" duration="10190000" />
|
||||||
|
<workItem from="1733644355292" duration="59000" />
|
||||||
|
<workItem from="1733644430242" duration="42000" />
|
||||||
|
<workItem from="1733688686708" duration="3433000" />
|
||||||
|
<workItem from="1733804654516" duration="339000" />
|
||||||
|
<workItem from="1733805003742" duration="9000" />
|
||||||
|
<workItem from="1733883751079" duration="757000" />
|
||||||
|
<workItem from="1733884522510" duration="3958000" />
|
||||||
|
<workItem from="1734052874393" duration="34000" />
|
||||||
|
</task>
|
||||||
|
<task id="LOCAL-00001" summary="Nano zoom fix #11">
|
||||||
|
<option name="closed" value="true" />
|
||||||
|
<created>1733447944692</created>
|
||||||
|
<option name="number" value="00001" />
|
||||||
|
<option name="presentableId" value="LOCAL-00001" />
|
||||||
|
<option name="project" value="LOCAL" />
|
||||||
|
<updated>1733447944692</updated>
|
||||||
|
</task>
|
||||||
|
<task id="LOCAL-00002" summary="Nano zoom fix #11">
|
||||||
|
<option name="closed" value="true" />
|
||||||
|
<created>1733448864234</created>
|
||||||
|
<option name="number" value="00002" />
|
||||||
|
<option name="presentableId" value="LOCAL-00002" />
|
||||||
|
<option name="project" value="LOCAL" />
|
||||||
|
<updated>1733448864234</updated>
|
||||||
|
</task>
|
||||||
|
<task id="LOCAL-00003" summary="Nano zoom fix #11">
|
||||||
|
<option name="closed" value="true" />
|
||||||
|
<created>1733449234908</created>
|
||||||
|
<option name="number" value="00003" />
|
||||||
|
<option name="presentableId" value="LOCAL-00003" />
|
||||||
|
<option name="project" value="LOCAL" />
|
||||||
|
<updated>1733449234908</updated>
|
||||||
|
</task>
|
||||||
|
<task id="LOCAL-00004" summary="Nano zoom fix #12">
|
||||||
|
<option name="closed" value="true" />
|
||||||
|
<created>1733449331913</created>
|
||||||
|
<option name="number" value="00004" />
|
||||||
|
<option name="presentableId" value="LOCAL-00004" />
|
||||||
|
<option name="project" value="LOCAL" />
|
||||||
|
<updated>1733449331913</updated>
|
||||||
|
</task>
|
||||||
|
<task id="LOCAL-00005" summary="Nano zoom fix #13">
|
||||||
|
<option name="closed" value="true" />
|
||||||
|
<created>1733449760767</created>
|
||||||
|
<option name="number" value="00005" />
|
||||||
|
<option name="presentableId" value="LOCAL-00005" />
|
||||||
|
<option name="project" value="LOCAL" />
|
||||||
|
<updated>1733449760767</updated>
|
||||||
|
</task>
|
||||||
|
<task id="LOCAL-00006" summary="Nano zoom fix #14">
|
||||||
|
<option name="closed" value="true" />
|
||||||
|
<created>1733450304640</created>
|
||||||
|
<option name="number" value="00006" />
|
||||||
|
<option name="presentableId" value="LOCAL-00006" />
|
||||||
|
<option name="project" value="LOCAL" />
|
||||||
|
<updated>1733450304640</updated>
|
||||||
|
</task>
|
||||||
|
<task id="LOCAL-00007" summary="Nano zoom fix #15">
|
||||||
|
<option name="closed" value="true" />
|
||||||
|
<created>1733450681262</created>
|
||||||
|
<option name="number" value="00007" />
|
||||||
|
<option name="presentableId" value="LOCAL-00007" />
|
||||||
|
<option name="project" value="LOCAL" />
|
||||||
|
<updated>1733450681262</updated>
|
||||||
|
</task>
|
||||||
|
<task id="LOCAL-00008" summary="Nano zoom fix #16 (ssh-2-promise)">
|
||||||
|
<option name="closed" value="true" />
|
||||||
|
<created>1733451925922</created>
|
||||||
|
<option name="number" value="00008" />
|
||||||
|
<option name="presentableId" value="LOCAL-00008" />
|
||||||
|
<option name="project" value="LOCAL" />
|
||||||
|
<updated>1733451925922</updated>
|
||||||
|
</task>
|
||||||
|
<task id="LOCAL-00009" summary="Full return back to old code with minor fixes">
|
||||||
|
<option name="closed" value="true" />
|
||||||
|
<created>1733532896448</created>
|
||||||
|
<option name="number" value="00009" />
|
||||||
|
<option name="presentableId" value="LOCAL-00009" />
|
||||||
|
<option name="project" value="LOCAL" />
|
||||||
|
<updated>1733532896448</updated>
|
||||||
|
</task>
|
||||||
|
<task id="LOCAL-00010" summary="Terminal size fix #18 (rows & cols fix)">
|
||||||
|
<option name="closed" value="true" />
|
||||||
|
<created>1733538097802</created>
|
||||||
|
<option name="number" value="00010" />
|
||||||
|
<option name="presentableId" value="LOCAL-00010" />
|
||||||
|
<option name="project" value="LOCAL" />
|
||||||
|
<updated>1733538097802</updated>
|
||||||
|
</task>
|
||||||
|
<task id="LOCAL-00011" summary="Test ntfy build notification system">
|
||||||
|
<option name="closed" value="true" />
|
||||||
|
<created>1733539381433</created>
|
||||||
|
<option name="number" value="00011" />
|
||||||
|
<option name="presentableId" value="LOCAL-00011" />
|
||||||
|
<option name="project" value="LOCAL" />
|
||||||
|
<updated>1733539381433</updated>
|
||||||
|
</task>
|
||||||
|
<task id="LOCAL-00012" summary="Silent resize cmds & Auto resize terminal #1">
|
||||||
|
<option name="closed" value="true" />
|
||||||
|
<created>1733553128900</created>
|
||||||
|
<option name="number" value="00012" />
|
||||||
|
<option name="presentableId" value="LOCAL-00012" />
|
||||||
|
<option name="project" value="LOCAL" />
|
||||||
|
<updated>1733553128900</updated>
|
||||||
|
</task>
|
||||||
|
<task id="LOCAL-00013" summary="Silent resize cmds & Auto resize terminal #2">
|
||||||
|
<option name="closed" value="true" />
|
||||||
|
<created>1733553902375</created>
|
||||||
|
<option name="number" value="00013" />
|
||||||
|
<option name="presentableId" value="LOCAL-00013" />
|
||||||
|
<option name="project" value="LOCAL" />
|
||||||
|
<updated>1733553902375</updated>
|
||||||
|
</task>
|
||||||
|
<task id="LOCAL-00014" summary="Docker build update">
|
||||||
|
<option name="closed" value="true" />
|
||||||
|
<created>1733555933987</created>
|
||||||
|
<option name="number" value="00014" />
|
||||||
|
<option name="presentableId" value="LOCAL-00014" />
|
||||||
|
<option name="project" value="LOCAL" />
|
||||||
|
<updated>1733555933987</updated>
|
||||||
|
</task>
|
||||||
|
<task id="LOCAL-00015" summary="Docker build update #2">
|
||||||
|
<option name="closed" value="true" />
|
||||||
|
<created>1733556269270</created>
|
||||||
|
<option name="number" value="00015" />
|
||||||
|
<option name="presentableId" value="LOCAL-00015" />
|
||||||
|
<option name="project" value="LOCAL" />
|
||||||
|
<updated>1733556269270</updated>
|
||||||
|
</task>
|
||||||
|
<task id="LOCAL-00016" summary="Docker build update #3">
|
||||||
|
<option name="closed" value="true" />
|
||||||
|
<created>1733556428424</created>
|
||||||
|
<option name="number" value="00016" />
|
||||||
|
<option name="presentableId" value="LOCAL-00016" />
|
||||||
|
<option name="project" value="LOCAL" />
|
||||||
|
<updated>1733556428424</updated>
|
||||||
|
</task>
|
||||||
|
<task id="LOCAL-00017" summary="Docker build update #4 (cache and cleanup)">
|
||||||
|
<option name="closed" value="true" />
|
||||||
|
<created>1733556699034</created>
|
||||||
|
<option name="number" value="00017" />
|
||||||
|
<option name="presentableId" value="LOCAL-00017" />
|
||||||
|
<option name="project" value="LOCAL" />
|
||||||
|
<updated>1733556699034</updated>
|
||||||
|
</task>
|
||||||
|
<task id="LOCAL-00018" summary="Docker build update #5 (cache and cleanup)">
|
||||||
|
<option name="closed" value="true" />
|
||||||
|
<created>1733556917800</created>
|
||||||
|
<option name="number" value="00018" />
|
||||||
|
<option name="presentableId" value="LOCAL-00018" />
|
||||||
|
<option name="project" value="LOCAL" />
|
||||||
|
<updated>1733556917800</updated>
|
||||||
|
</task>
|
||||||
|
<task id="LOCAL-00019" summary="Docker build update #5 (cache and cleanup)">
|
||||||
|
<option name="closed" value="true" />
|
||||||
|
<created>1733557286584</created>
|
||||||
|
<option name="number" value="00019" />
|
||||||
|
<option name="presentableId" value="LOCAL-00019" />
|
||||||
|
<option name="project" value="LOCAL" />
|
||||||
|
<updated>1733557286584</updated>
|
||||||
|
</task>
|
||||||
|
<task id="LOCAL-00020" summary="Docker build update #6 (cache and cleanup)">
|
||||||
|
<option name="closed" value="true" />
|
||||||
|
<created>1733557337662</created>
|
||||||
|
<option name="number" value="00020" />
|
||||||
|
<option name="presentableId" value="LOCAL-00020" />
|
||||||
|
<option name="project" value="LOCAL" />
|
||||||
|
<updated>1733557337662</updated>
|
||||||
|
</task>
|
||||||
|
<task id="LOCAL-00021" summary="Docker build update #7 (final)">
|
||||||
|
<option name="closed" value="true" />
|
||||||
|
<created>1733557558085</created>
|
||||||
|
<option name="number" value="00021" />
|
||||||
|
<option name="presentableId" value="LOCAL-00021" />
|
||||||
|
<option name="project" value="LOCAL" />
|
||||||
|
<updated>1733557558085</updated>
|
||||||
|
</task>
|
||||||
|
<task id="LOCAL-00022" summary="Docker build update #8 (nevermind not finanl)">
|
||||||
|
<option name="closed" value="true" />
|
||||||
|
<created>1733557773727</created>
|
||||||
|
<option name="number" value="00022" />
|
||||||
|
<option name="presentableId" value="LOCAL-00022" />
|
||||||
|
<option name="project" value="LOCAL" />
|
||||||
|
<updated>1733557773727</updated>
|
||||||
|
</task>
|
||||||
|
<task id="LOCAL-00023" summary="Docker build update #9 (nevermind not finanl)">
|
||||||
|
<option name="closed" value="true" />
|
||||||
|
<created>1733558138278</created>
|
||||||
|
<option name="number" value="00023" />
|
||||||
|
<option name="presentableId" value="LOCAL-00023" />
|
||||||
|
<option name="project" value="LOCAL" />
|
||||||
|
<updated>1733558138278</updated>
|
||||||
|
</task>
|
||||||
|
<task id="LOCAL-00024" summary="Docker build update #10">
|
||||||
|
<option name="closed" value="true" />
|
||||||
|
<created>1733558347319</created>
|
||||||
|
<option name="number" value="00024" />
|
||||||
|
<option name="presentableId" value="LOCAL-00024" />
|
||||||
|
<option name="project" value="LOCAL" />
|
||||||
|
<updated>1733558347319</updated>
|
||||||
|
</task>
|
||||||
|
<task id="LOCAL-00025" summary="Docker build update #10 (I hope final)">
|
||||||
|
<option name="closed" value="true" />
|
||||||
|
<created>1733558781194</created>
|
||||||
|
<option name="number" value="00025" />
|
||||||
|
<option name="presentableId" value="LOCAL-00025" />
|
||||||
|
<option name="project" value="LOCAL" />
|
||||||
|
<updated>1733558781194</updated>
|
||||||
|
</task>
|
||||||
|
<task id="LOCAL-00026" summary="Docker build update #10 (actual final)">
|
||||||
|
<option name="closed" value="true" />
|
||||||
|
<created>1733558952696</created>
|
||||||
|
<option name="number" value="00026" />
|
||||||
|
<option name="presentableId" value="LOCAL-00026" />
|
||||||
|
<option name="project" value="LOCAL" />
|
||||||
|
<updated>1733558952696</updated>
|
||||||
|
</task>
|
||||||
|
<task id="LOCAL-00027" summary="Release 1.0!!!!">
|
||||||
|
<option name="closed" value="true" />
|
||||||
|
<created>1733603759658</created>
|
||||||
|
<option name="number" value="00027" />
|
||||||
|
<option name="presentableId" value="LOCAL-00027" />
|
||||||
|
<option name="project" value="LOCAL" />
|
||||||
|
<updated>1733603759658</updated>
|
||||||
|
</task>
|
||||||
|
<task id="LOCAL-00028" summary="Update README.md #4">
|
||||||
|
<option name="closed" value="true" />
|
||||||
|
<created>1733688870582</created>
|
||||||
|
<option name="number" value="00028" />
|
||||||
|
<option name="presentableId" value="LOCAL-00028" />
|
||||||
|
<option name="project" value="LOCAL" />
|
||||||
|
<updated>1733688870582</updated>
|
||||||
|
</task>
|
||||||
|
<task id="LOCAL-00029" summary="Add images">
|
||||||
|
<option name="closed" value="true" />
|
||||||
|
<created>1733691729582</created>
|
||||||
|
<option name="number" value="00029" />
|
||||||
|
<option name="presentableId" value="LOCAL-00029" />
|
||||||
|
<option name="project" value="LOCAL" />
|
||||||
|
<updated>1733691729582</updated>
|
||||||
|
</task>
|
||||||
|
<task id="LOCAL-00030" summary="Update image name">
|
||||||
|
<option name="closed" value="true" />
|
||||||
|
<created>1733691982293</created>
|
||||||
|
<option name="number" value="00030" />
|
||||||
|
<option name="presentableId" value="LOCAL-00030" />
|
||||||
|
<option name="project" value="LOCAL" />
|
||||||
|
<updated>1733691982293</updated>
|
||||||
|
</task>
|
||||||
|
<task id="LOCAL-00031" summary="Final changes to release-1.0">
|
||||||
|
<option name="closed" value="true" />
|
||||||
|
<created>1733692181011</created>
|
||||||
|
<option name="number" value="00031" />
|
||||||
|
<option name="presentableId" value="LOCAL-00031" />
|
||||||
|
<option name="project" value="LOCAL" />
|
||||||
|
<updated>1733692181011</updated>
|
||||||
|
</task>
|
||||||
|
<task id="LOCAL-00032" summary="Update name (need to fix logo)">
|
||||||
|
<option name="closed" value="true" />
|
||||||
|
<created>1733692962039</created>
|
||||||
|
<option name="number" value="00032" />
|
||||||
|
<option name="presentableId" value="LOCAL-00032" />
|
||||||
|
<option name="project" value="LOCAL" />
|
||||||
|
<updated>1733692962039</updated>
|
||||||
|
</task>
|
||||||
|
<task id="LOCAL-00033" summary="Final updates (I hope for real this time)">
|
||||||
|
<option name="closed" value="true" />
|
||||||
|
<created>1733886236040</created>
|
||||||
|
<option name="number" value="00033" />
|
||||||
|
<option name="presentableId" value="LOCAL-00033" />
|
||||||
|
<option name="project" value="LOCAL" />
|
||||||
|
<updated>1733886236040</updated>
|
||||||
|
</task>
|
||||||
|
<task id="LOCAL-00034" summary="Fix web-socket timeout.">
|
||||||
|
<option name="closed" value="true" />
|
||||||
|
<created>1733887722496</created>
|
||||||
|
<option name="number" value="00034" />
|
||||||
|
<option name="presentableId" value="LOCAL-00034" />
|
||||||
|
<option name="project" value="LOCAL" />
|
||||||
|
<updated>1733887722496</updated>
|
||||||
|
</task>
|
||||||
|
<task id="LOCAL-00035" summary="Fix timeout on close.">
|
||||||
|
<option name="closed" value="true" />
|
||||||
|
<created>1733887980750</created>
|
||||||
|
<option name="number" value="00035" />
|
||||||
|
<option name="presentableId" value="LOCAL-00035" />
|
||||||
|
<option name="project" value="LOCAL" />
|
||||||
|
<updated>1733887980750</updated>
|
||||||
|
</task>
|
||||||
|
<option name="localTasksCounter" value="36" />
|
||||||
|
<servers />
|
||||||
|
</component>
|
||||||
|
<component name="TypeScriptGeneratedFilesManager">
|
||||||
|
<option name="version" value="3" />
|
||||||
|
</component>
|
||||||
|
<component name="Vcs.Log.Tabs.Properties">
|
||||||
|
<option name="TAB_STATES">
|
||||||
|
<map>
|
||||||
|
<entry key="MAIN">
|
||||||
|
<value>
|
||||||
|
<State />
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
</map>
|
||||||
|
</option>
|
||||||
|
</component>
|
||||||
|
<component name="VcsManagerConfiguration">
|
||||||
|
<MESSAGE value="Terminal size fix #18 (rows & cols fix)" />
|
||||||
|
<MESSAGE value="Test ntfy build notification system" />
|
||||||
|
<MESSAGE value="Silent resize cmds & Auto resize terminal #1" />
|
||||||
|
<MESSAGE value="Silent resize cmds & Auto resize terminal #2" />
|
||||||
|
<MESSAGE value="Docker build update" />
|
||||||
|
<MESSAGE value="Docker build update #2" />
|
||||||
|
<MESSAGE value="Docker build update #3" />
|
||||||
|
<MESSAGE value="Docker build update #4 (cache and cleanup)" />
|
||||||
|
<MESSAGE value="Docker build update #5 (cache and cleanup)" />
|
||||||
|
<MESSAGE value="Docker build update #6 (cache and cleanup)" />
|
||||||
|
<MESSAGE value="Docker build update #7 (final)" />
|
||||||
|
<MESSAGE value="Docker build update #8 (nevermind not finanl)" />
|
||||||
|
<MESSAGE value="Docker build update #9 (nevermind not finanl)" />
|
||||||
|
<MESSAGE value="Docker build update #10" />
|
||||||
|
<MESSAGE value="Docker build update #10 (I hope final)" />
|
||||||
|
<MESSAGE value="Docker build update #10 (actual final)" />
|
||||||
|
<MESSAGE value="Release 1.0!!!!" />
|
||||||
|
<MESSAGE value="Update README.md #4" />
|
||||||
|
<MESSAGE value="Add images" />
|
||||||
|
<MESSAGE value="Update image name" />
|
||||||
|
<MESSAGE value="Final changes to release-1.0" />
|
||||||
|
<MESSAGE value="Update name (need to fix logo)" />
|
||||||
|
<MESSAGE value="Final updates (I hope for real this time)" />
|
||||||
|
<MESSAGE value="Fix web-socket timeout." />
|
||||||
|
<MESSAGE value="Fix timeout on close." />
|
||||||
|
<option name="LAST_COMMIT_MESSAGE" value="Fix timeout on close." />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
21
LICENSE
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2024 Luke Gustafson
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
50
README.md
@@ -1 +1,49 @@
|
|||||||
SSH is silly
|
# Repo Stats
|
||||||
|

|
||||||
|

|
||||||
|

|
||||||
|
#### Top Technologies
|
||||||
|
[](#)
|
||||||
|
[](#)
|
||||||
|
[](#)
|
||||||
|
[](#)
|
||||||
|
[](#)
|
||||||
|
[](#)
|
||||||
|
|
||||||
|
<br />
|
||||||
|
<p align="center">
|
||||||
|
<a href="https://github.com/LukeGus/Termix">
|
||||||
|
<img alt="Termimx Banner" src=./repo-images/TermixLogo.png style="width: 125px; height: auto;"> </a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
# Description
|
||||||
|
Termix is an open-source forever free self-hosted SSH (other protocols planned, see [Planned Features](#planned-features)) management panel inspired by [Nexterm](https://github.com/gnmyt/Nexterm). Its purpose is to provide an all-in-one docker-hosted web solution to manage your servers in one easy place. I'm using this project to help me learn [React](https://github.com/facebook/react), [Vite](https://github.com/vitejs/vite-plugin-react), and [Docker](https://www.docker.com) but also because I could never settle on a server management software that I enjoyed to use.
|
||||||
|
|
||||||
|
> [!WARNING]
|
||||||
|
> This app is in the VERY early stages of development. Expect bugs, data loss, and possibly even security issues!
|
||||||
|
|
||||||
|
# Planned Features
|
||||||
|
- [x] SSH
|
||||||
|
- [ ] VNC
|
||||||
|
- [ ] RDP
|
||||||
|
- [ ] SMTP (build in file transfer)
|
||||||
|
- [ ] Split Screen & Tabs
|
||||||
|
- [ ] ChatGPT/Ollama Integration (for commands)
|
||||||
|
- [ ] Login Screen
|
||||||
|
|
||||||
|
# How Termix is Different
|
||||||
|
Before developing Termix, I faced the issue of a server management panel that did not have every feature I liked. [Guacamole](https://guacamole.apache.org/) had poor copy/paste abilities and a poor UI. [Shellngn](https://shellngn.com/) was too expensive and all other alternatives had one major problem with them. I plan to develop the management panel of my dreams with even an AI integration for those pesky commands I always forget the syntax of.
|
||||||
|
|
||||||
|
# Installation
|
||||||
|
View the Termix [Wiki](https://github.com/LukeGus/Termix/wiki) for information on how to install Termix. You can also use these links to go directly to guide. [Docker](https://github.com/LukeGus/Termix/wiki/Docker) or [Manual](https://github.com/LukeGus/Termix/wiki/Manual).
|
||||||
|
|
||||||
|
# Known Bugs
|
||||||
|
### Please create an [Issue](https://github.com/LukeGus/Termix/issues) if you find any problems!
|
||||||
|
Start session button stays connected even if SSH fails to connect.
|
||||||
|
|
||||||
|
# Show-off
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
# License
|
||||||
|
Distributed under the MIT license. See LICENSE for more information.
|
||||||
|
|||||||
73
backend/package-lock.json
generated
@@ -11,6 +11,8 @@
|
|||||||
"@testing-library/jest-dom": "^5.16.5",
|
"@testing-library/jest-dom": "^5.16.5",
|
||||||
"@testing-library/react": "^13.4.0",
|
"@testing-library/react": "^13.4.0",
|
||||||
"@testing-library/user-event": "^14.4.3",
|
"@testing-library/user-event": "^14.4.3",
|
||||||
|
"@xterm/addon-fit": "^0.10.0",
|
||||||
|
"@xterm/xterm": "^5.5.0",
|
||||||
"express": "^4.21.1",
|
"express": "^4.21.1",
|
||||||
"guacamole-common-js": "^1.5.0",
|
"guacamole-common-js": "^1.5.0",
|
||||||
"http-proxy-middleware": "^3.0.3",
|
"http-proxy-middleware": "^3.0.3",
|
||||||
@@ -1501,6 +1503,19 @@
|
|||||||
"integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==",
|
"integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/@xterm/addon-fit": {
|
||||||
|
"version": "0.10.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@xterm/addon-fit/-/addon-fit-0.10.0.tgz",
|
||||||
|
"integrity": "sha512-UFYkDm4HUahf2lnEyHvio51TNGiLK66mqP2JoATy7hRZeXaGMRDr00JiSF7m63vR5WKATF605yEggJKsw0JpMQ==",
|
||||||
|
"peerDependencies": {
|
||||||
|
"@xterm/xterm": "^5.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@xterm/xterm": {
|
||||||
|
"version": "5.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@xterm/xterm/-/xterm-5.5.0.tgz",
|
||||||
|
"integrity": "sha512-hqJHYaQb5OptNunnyAnkHyM8aCjZ1MEIDTQu1iIbbTD/xops91NB5yq1ZK/dC2JDbVWtF23zUtl9JE2NqwT87A=="
|
||||||
|
},
|
||||||
"node_modules/abab": {
|
"node_modules/abab": {
|
||||||
"version": "2.0.6",
|
"version": "2.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz",
|
||||||
@@ -2288,10 +2303,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/express": {
|
"node_modules/express": {
|
||||||
"version": "4.21.1",
|
"version": "4.21.2",
|
||||||
"resolved": "https://registry.npmjs.org/express/-/express-4.21.1.tgz",
|
"resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz",
|
||||||
"integrity": "sha512-YSFlK1Ee0/GC8QaO91tHcDxJiE/X4FbpAyQWkxAvG6AXCuR65YzK8ua6D9hvi/TzUfZMpc+BwuM1IPw8fmQBiQ==",
|
"integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==",
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"accepts": "~1.3.8",
|
"accepts": "~1.3.8",
|
||||||
"array-flatten": "1.1.1",
|
"array-flatten": "1.1.1",
|
||||||
@@ -2312,7 +2326,7 @@
|
|||||||
"methods": "~1.1.2",
|
"methods": "~1.1.2",
|
||||||
"on-finished": "2.4.1",
|
"on-finished": "2.4.1",
|
||||||
"parseurl": "~1.3.3",
|
"parseurl": "~1.3.3",
|
||||||
"path-to-regexp": "0.1.10",
|
"path-to-regexp": "0.1.12",
|
||||||
"proxy-addr": "~2.0.7",
|
"proxy-addr": "~2.0.7",
|
||||||
"qs": "6.13.0",
|
"qs": "6.13.0",
|
||||||
"range-parser": "~1.2.1",
|
"range-parser": "~1.2.1",
|
||||||
@@ -2327,6 +2341,10 @@
|
|||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 0.10.0"
|
"node": ">= 0.10.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/express"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/express/node_modules/debug": {
|
"node_modules/express/node_modules/debug": {
|
||||||
@@ -3394,9 +3412,9 @@
|
|||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
"node_modules/nanoid": {
|
"node_modules/nanoid": {
|
||||||
"version": "3.3.6",
|
"version": "3.3.8",
|
||||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz",
|
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz",
|
||||||
"integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==",
|
"integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@@ -3404,6 +3422,7 @@
|
|||||||
"url": "https://github.com/sponsors/ai"
|
"url": "https://github.com/sponsors/ai"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"license": "MIT",
|
||||||
"bin": {
|
"bin": {
|
||||||
"nanoid": "bin/nanoid.cjs"
|
"nanoid": "bin/nanoid.cjs"
|
||||||
},
|
},
|
||||||
@@ -3539,10 +3558,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/path-to-regexp": {
|
"node_modules/path-to-regexp": {
|
||||||
"version": "0.1.10",
|
"version": "0.1.12",
|
||||||
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz",
|
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz",
|
||||||
"integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==",
|
"integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ=="
|
||||||
"license": "MIT"
|
|
||||||
},
|
},
|
||||||
"node_modules/pathe": {
|
"node_modules/pathe": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
@@ -5774,6 +5792,17 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@xterm/addon-fit": {
|
||||||
|
"version": "0.10.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@xterm/addon-fit/-/addon-fit-0.10.0.tgz",
|
||||||
|
"integrity": "sha512-UFYkDm4HUahf2lnEyHvio51TNGiLK66mqP2JoATy7hRZeXaGMRDr00JiSF7m63vR5WKATF605yEggJKsw0JpMQ==",
|
||||||
|
"requires": {}
|
||||||
|
},
|
||||||
|
"@xterm/xterm": {
|
||||||
|
"version": "5.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@xterm/xterm/-/xterm-5.5.0.tgz",
|
||||||
|
"integrity": "sha512-hqJHYaQb5OptNunnyAnkHyM8aCjZ1MEIDTQu1iIbbTD/xops91NB5yq1ZK/dC2JDbVWtF23zUtl9JE2NqwT87A=="
|
||||||
|
},
|
||||||
"abab": {
|
"abab": {
|
||||||
"version": "2.0.6",
|
"version": "2.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz",
|
||||||
@@ -6320,9 +6349,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"express": {
|
"express": {
|
||||||
"version": "4.21.1",
|
"version": "4.21.2",
|
||||||
"resolved": "https://registry.npmjs.org/express/-/express-4.21.1.tgz",
|
"resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz",
|
||||||
"integrity": "sha512-YSFlK1Ee0/GC8QaO91tHcDxJiE/X4FbpAyQWkxAvG6AXCuR65YzK8ua6D9hvi/TzUfZMpc+BwuM1IPw8fmQBiQ==",
|
"integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"accepts": "~1.3.8",
|
"accepts": "~1.3.8",
|
||||||
"array-flatten": "1.1.1",
|
"array-flatten": "1.1.1",
|
||||||
@@ -6343,7 +6372,7 @@
|
|||||||
"methods": "~1.1.2",
|
"methods": "~1.1.2",
|
||||||
"on-finished": "2.4.1",
|
"on-finished": "2.4.1",
|
||||||
"parseurl": "~1.3.3",
|
"parseurl": "~1.3.3",
|
||||||
"path-to-regexp": "0.1.10",
|
"path-to-regexp": "0.1.12",
|
||||||
"proxy-addr": "~2.0.7",
|
"proxy-addr": "~2.0.7",
|
||||||
"qs": "6.13.0",
|
"qs": "6.13.0",
|
||||||
"range-parser": "~1.2.1",
|
"range-parser": "~1.2.1",
|
||||||
@@ -7096,9 +7125,9 @@
|
|||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
"nanoid": {
|
"nanoid": {
|
||||||
"version": "3.3.6",
|
"version": "3.3.8",
|
||||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz",
|
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz",
|
||||||
"integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==",
|
"integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"negotiator": {
|
"negotiator": {
|
||||||
@@ -7185,9 +7214,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"path-to-regexp": {
|
"path-to-regexp": {
|
||||||
"version": "0.1.10",
|
"version": "0.1.12",
|
||||||
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz",
|
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz",
|
||||||
"integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w=="
|
"integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ=="
|
||||||
},
|
},
|
||||||
"pathe": {
|
"pathe": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
|
|||||||
@@ -6,6 +6,8 @@
|
|||||||
"@testing-library/jest-dom": "^5.16.5",
|
"@testing-library/jest-dom": "^5.16.5",
|
||||||
"@testing-library/react": "^13.4.0",
|
"@testing-library/react": "^13.4.0",
|
||||||
"@testing-library/user-event": "^14.4.3",
|
"@testing-library/user-event": "^14.4.3",
|
||||||
|
"@xterm/addon-fit": "^0.10.0",
|
||||||
|
"@xterm/xterm": "^5.5.0",
|
||||||
"express": "^4.21.1",
|
"express": "^4.21.1",
|
||||||
"guacamole-common-js": "^1.5.0",
|
"guacamole-common-js": "^1.5.0",
|
||||||
"http-proxy-middleware": "^3.0.3",
|
"http-proxy-middleware": "^3.0.3",
|
||||||
@@ -55,4 +57,4 @@
|
|||||||
"vite": "^4.5.5",
|
"vite": "^4.5.5",
|
||||||
"vitest": "^0.34.6"
|
"vitest": "^0.34.6"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,97 +2,104 @@ const WebSocket = require('ws');
|
|||||||
const ssh2 = require('ssh2');
|
const ssh2 = require('ssh2');
|
||||||
const http = require('http');
|
const http = require('http');
|
||||||
|
|
||||||
// Create an HTTP server to serve WebSocket connections
|
|
||||||
const server = http.createServer((req, res) => {
|
const server = http.createServer((req, res) => {
|
||||||
res.writeHead(200, { 'Content-Type': 'text/plain' });
|
res.writeHead(200, { 'Content-Type': 'text/plain' });
|
||||||
res.end('WebSocket server is running\n');
|
res.end('WebSocket server is running\n');
|
||||||
});
|
});
|
||||||
|
|
||||||
// Create a WebSocket server attached to the HTTP server
|
|
||||||
const wss = new WebSocket.Server({ server });
|
const wss = new WebSocket.Server({ server });
|
||||||
|
|
||||||
// WebSocket connection handling
|
|
||||||
wss.on('connection', (ws) => {
|
wss.on('connection', (ws) => {
|
||||||
console.log('WebSocket connection established');
|
console.log('WebSocket connection established');
|
||||||
|
|
||||||
let conn = null; // Declare SSH client outside to manage lifecycle
|
let conn = new ssh2.Client();
|
||||||
|
let stream = null;
|
||||||
|
let currentCols = 80;
|
||||||
|
let currentRows = 24;
|
||||||
|
let interval = null;
|
||||||
|
|
||||||
ws.on('message', (message) => {
|
const resizeTerminal = (cols, rows) => {
|
||||||
try {
|
if (stream && stream.setWindow) {
|
||||||
const data = JSON.parse(message); // Try parsing the incoming message as JSON
|
stream.setWindow(rows, cols, rows * 100, cols * 100); // Adjust terminal size
|
||||||
|
console.log(`Terminal resized successfully: cols=${cols}, rows=${rows}`);
|
||||||
// Check if message contains SSH connection details
|
|
||||||
if (data.host && data.username && data.password) {
|
|
||||||
if (conn) {
|
|
||||||
conn.end(); // Close any previous connection before starting a new one
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
conn = new ssh2.Client(); // Create a new SSH connection instance
|
ws.on('message', (message) => {
|
||||||
|
const messageStr = message.toString();
|
||||||
|
|
||||||
// When the SSH connection is ready
|
let data;
|
||||||
conn.on('ready', () => {
|
try {
|
||||||
console.log('SSH Connection established');
|
if (messageStr.trim().startsWith('{')) {
|
||||||
|
data = JSON.parse(messageStr);
|
||||||
// Start an interactive shell session
|
} else if (stream && stream.writable) {
|
||||||
conn.shell((err, stream) => {
|
stream.write(messageStr);
|
||||||
if (err) {
|
return;
|
||||||
console.log(`SSH Error: ${err}`);
|
|
||||||
ws.send(`Error: ${err}`);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
} catch (error) {
|
||||||
// Handle data from SSH session
|
console.error('Failed to process message:', error);
|
||||||
stream.on('data', (data) => {
|
return;
|
||||||
console.log(`SSH Output: ${data}`);
|
|
||||||
ws.send(data.toString()); // Send the SSH output back to WebSocket client
|
|
||||||
});
|
|
||||||
|
|
||||||
// Handle stream close event
|
|
||||||
stream.on('close', () => {
|
|
||||||
console.log('SSH stream closed');
|
|
||||||
conn.end();
|
|
||||||
});
|
|
||||||
|
|
||||||
// When the WebSocket client sends a message (from terminal input), forward it to the SSH stream
|
|
||||||
ws.on('message', (message) => {
|
|
||||||
console.log(`Received message from WebSocket: ${message}`);
|
|
||||||
stream.write(message); // Write the message (input) to the SSH shell
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}).on('error', (err) => {
|
|
||||||
console.log('SSH Connection Error: ', err);
|
|
||||||
ws.send(`SSH Error: ${err}`);
|
|
||||||
}).connect({
|
|
||||||
host: data.host, // Host provided from the client
|
|
||||||
port: 22, // Default SSH port
|
|
||||||
username: data.username, // Username provided from the client
|
|
||||||
password: data.password, // Password provided from the client
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
// If message is not valid JSON (i.e., terminal input), treat it as raw text and send it to SSH
|
|
||||||
console.log('Received non-JSON message, sending to SSH session:', message);
|
|
||||||
if (conn) {
|
|
||||||
const stream = conn._stream; // Access the SSH stream directly
|
|
||||||
if (stream && stream.writable) {
|
|
||||||
stream.write(message); // Write raw input message to SSH stream
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
console.error('SSH connection is not established yet.');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Handle WebSocket close event
|
if (data?.host && data.port && data.username && data.password) {
|
||||||
ws.on('close', () => {
|
conn.on('ready', () => {
|
||||||
console.log('WebSocket closed');
|
console.log('SSH Connection established');
|
||||||
if (conn) {
|
|
||||||
conn.end(); // Close SSH connection when WebSocket client disconnects
|
interval = setInterval(() => {
|
||||||
}
|
if (ws.readyState === WebSocket.OPEN) {
|
||||||
});
|
ws.ping();
|
||||||
|
} else {
|
||||||
|
clearInterval(interval);
|
||||||
|
}
|
||||||
|
}, 15000);
|
||||||
|
|
||||||
|
conn.shell({ term: 'xterm', cols: currentCols, rows: currentRows }, (error, newStream) => {
|
||||||
|
if (error) {
|
||||||
|
console.error(`SSH Shell Error: ${error}`);
|
||||||
|
ws.send(`Error: Could not establish a shell: ${error.message}`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
stream = newStream;
|
||||||
|
|
||||||
|
stream.on('data', (chunk) => {
|
||||||
|
ws.send(chunk.toString());
|
||||||
|
});
|
||||||
|
|
||||||
|
stream.on('close', () => {
|
||||||
|
console.log('SSH stream closed');
|
||||||
|
conn.end();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}).on('error', (err) => {
|
||||||
|
console.log('SSH Connection Error:', err);
|
||||||
|
ws.send(`SSH Connection Error: ${err.message}`);
|
||||||
|
}).connect({
|
||||||
|
host: data.host,
|
||||||
|
port: data.port,
|
||||||
|
username: data.username,
|
||||||
|
password: data.password,
|
||||||
|
keepaliveInterval: 10000,
|
||||||
|
keepaliveCountMax: 5,
|
||||||
|
});
|
||||||
|
} else if (data?.cols && data.rows) {
|
||||||
|
currentCols = data.cols;
|
||||||
|
currentRows = data.rows;
|
||||||
|
resizeTerminal(currentCols, currentRows);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
ws.on('close', () => {
|
||||||
|
console.log('WebSocket closed');
|
||||||
|
if (interval) {
|
||||||
|
clearInterval(interval);
|
||||||
|
}
|
||||||
|
if (conn) {
|
||||||
|
conn.end();
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// Start the WebSocket server on port 8081
|
|
||||||
server.listen(8081, () => {
|
server.listen(8081, () => {
|
||||||
console.log('WebSocket server is listening on ws://localhost:8081');
|
console.log('WebSocket server is listening on ws://localhost:8081');
|
||||||
});
|
});
|
||||||
BIN
frontend/favicon.ico
Normal file
|
After Width: | Height: | Size: 4.2 KiB |
@@ -2,12 +2,12 @@
|
|||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<link rel="icon" href="/favicon.ico" />
|
<link rel="icon" href="/favicon.ico?v=2" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
<meta name="theme-color" content="#000000" />
|
<meta name="theme-color" content="#000000" />
|
||||||
<meta
|
<meta
|
||||||
name="description"
|
name="description"
|
||||||
content="Web site created using @vitejs/plugin-react"
|
content="Sever management software for SSH!"
|
||||||
/>
|
/>
|
||||||
<link rel="apple-touch-icon" href="/logo192.png" />
|
<link rel="apple-touch-icon" href="/logo192.png" />
|
||||||
<!--
|
<!--
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
|
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
|
||||||
-->
|
-->
|
||||||
<link rel="manifest" href="/manifest.json" />
|
<link rel="manifest" href="/manifest.json" />
|
||||||
<title>React App</title>
|
<title>Termix</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||||
|
|||||||
73
frontend/package-lock.json
generated
@@ -11,6 +11,8 @@
|
|||||||
"@testing-library/jest-dom": "^5.16.5",
|
"@testing-library/jest-dom": "^5.16.5",
|
||||||
"@testing-library/react": "^13.4.0",
|
"@testing-library/react": "^13.4.0",
|
||||||
"@testing-library/user-event": "^14.4.3",
|
"@testing-library/user-event": "^14.4.3",
|
||||||
|
"@xterm/addon-fit": "^0.10.0",
|
||||||
|
"@xterm/xterm": "^5.5.0",
|
||||||
"express": "^4.21.1",
|
"express": "^4.21.1",
|
||||||
"guacamole-common-js": "^1.5.0",
|
"guacamole-common-js": "^1.5.0",
|
||||||
"http-proxy-middleware": "^3.0.3",
|
"http-proxy-middleware": "^3.0.3",
|
||||||
@@ -1501,6 +1503,19 @@
|
|||||||
"integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==",
|
"integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/@xterm/addon-fit": {
|
||||||
|
"version": "0.10.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@xterm/addon-fit/-/addon-fit-0.10.0.tgz",
|
||||||
|
"integrity": "sha512-UFYkDm4HUahf2lnEyHvio51TNGiLK66mqP2JoATy7hRZeXaGMRDr00JiSF7m63vR5WKATF605yEggJKsw0JpMQ==",
|
||||||
|
"peerDependencies": {
|
||||||
|
"@xterm/xterm": "^5.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@xterm/xterm": {
|
||||||
|
"version": "5.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@xterm/xterm/-/xterm-5.5.0.tgz",
|
||||||
|
"integrity": "sha512-hqJHYaQb5OptNunnyAnkHyM8aCjZ1MEIDTQu1iIbbTD/xops91NB5yq1ZK/dC2JDbVWtF23zUtl9JE2NqwT87A=="
|
||||||
|
},
|
||||||
"node_modules/abab": {
|
"node_modules/abab": {
|
||||||
"version": "2.0.6",
|
"version": "2.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz",
|
||||||
@@ -2288,10 +2303,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/express": {
|
"node_modules/express": {
|
||||||
"version": "4.21.1",
|
"version": "4.21.2",
|
||||||
"resolved": "https://registry.npmjs.org/express/-/express-4.21.1.tgz",
|
"resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz",
|
||||||
"integrity": "sha512-YSFlK1Ee0/GC8QaO91tHcDxJiE/X4FbpAyQWkxAvG6AXCuR65YzK8ua6D9hvi/TzUfZMpc+BwuM1IPw8fmQBiQ==",
|
"integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==",
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"accepts": "~1.3.8",
|
"accepts": "~1.3.8",
|
||||||
"array-flatten": "1.1.1",
|
"array-flatten": "1.1.1",
|
||||||
@@ -2312,7 +2326,7 @@
|
|||||||
"methods": "~1.1.2",
|
"methods": "~1.1.2",
|
||||||
"on-finished": "2.4.1",
|
"on-finished": "2.4.1",
|
||||||
"parseurl": "~1.3.3",
|
"parseurl": "~1.3.3",
|
||||||
"path-to-regexp": "0.1.10",
|
"path-to-regexp": "0.1.12",
|
||||||
"proxy-addr": "~2.0.7",
|
"proxy-addr": "~2.0.7",
|
||||||
"qs": "6.13.0",
|
"qs": "6.13.0",
|
||||||
"range-parser": "~1.2.1",
|
"range-parser": "~1.2.1",
|
||||||
@@ -2327,6 +2341,10 @@
|
|||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 0.10.0"
|
"node": ">= 0.10.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/express"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/express/node_modules/debug": {
|
"node_modules/express/node_modules/debug": {
|
||||||
@@ -3394,9 +3412,9 @@
|
|||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
"node_modules/nanoid": {
|
"node_modules/nanoid": {
|
||||||
"version": "3.3.6",
|
"version": "3.3.8",
|
||||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz",
|
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz",
|
||||||
"integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==",
|
"integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@@ -3404,6 +3422,7 @@
|
|||||||
"url": "https://github.com/sponsors/ai"
|
"url": "https://github.com/sponsors/ai"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"license": "MIT",
|
||||||
"bin": {
|
"bin": {
|
||||||
"nanoid": "bin/nanoid.cjs"
|
"nanoid": "bin/nanoid.cjs"
|
||||||
},
|
},
|
||||||
@@ -3539,10 +3558,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/path-to-regexp": {
|
"node_modules/path-to-regexp": {
|
||||||
"version": "0.1.10",
|
"version": "0.1.12",
|
||||||
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz",
|
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz",
|
||||||
"integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==",
|
"integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ=="
|
||||||
"license": "MIT"
|
|
||||||
},
|
},
|
||||||
"node_modules/pathe": {
|
"node_modules/pathe": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
@@ -5773,6 +5791,17 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@xterm/addon-fit": {
|
||||||
|
"version": "0.10.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@xterm/addon-fit/-/addon-fit-0.10.0.tgz",
|
||||||
|
"integrity": "sha512-UFYkDm4HUahf2lnEyHvio51TNGiLK66mqP2JoATy7hRZeXaGMRDr00JiSF7m63vR5WKATF605yEggJKsw0JpMQ==",
|
||||||
|
"requires": {}
|
||||||
|
},
|
||||||
|
"@xterm/xterm": {
|
||||||
|
"version": "5.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@xterm/xterm/-/xterm-5.5.0.tgz",
|
||||||
|
"integrity": "sha512-hqJHYaQb5OptNunnyAnkHyM8aCjZ1MEIDTQu1iIbbTD/xops91NB5yq1ZK/dC2JDbVWtF23zUtl9JE2NqwT87A=="
|
||||||
|
},
|
||||||
"abab": {
|
"abab": {
|
||||||
"version": "2.0.6",
|
"version": "2.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz",
|
||||||
@@ -6319,9 +6348,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"express": {
|
"express": {
|
||||||
"version": "4.21.1",
|
"version": "4.21.2",
|
||||||
"resolved": "https://registry.npmjs.org/express/-/express-4.21.1.tgz",
|
"resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz",
|
||||||
"integrity": "sha512-YSFlK1Ee0/GC8QaO91tHcDxJiE/X4FbpAyQWkxAvG6AXCuR65YzK8ua6D9hvi/TzUfZMpc+BwuM1IPw8fmQBiQ==",
|
"integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"accepts": "~1.3.8",
|
"accepts": "~1.3.8",
|
||||||
"array-flatten": "1.1.1",
|
"array-flatten": "1.1.1",
|
||||||
@@ -6342,7 +6371,7 @@
|
|||||||
"methods": "~1.1.2",
|
"methods": "~1.1.2",
|
||||||
"on-finished": "2.4.1",
|
"on-finished": "2.4.1",
|
||||||
"parseurl": "~1.3.3",
|
"parseurl": "~1.3.3",
|
||||||
"path-to-regexp": "0.1.10",
|
"path-to-regexp": "0.1.12",
|
||||||
"proxy-addr": "~2.0.7",
|
"proxy-addr": "~2.0.7",
|
||||||
"qs": "6.13.0",
|
"qs": "6.13.0",
|
||||||
"range-parser": "~1.2.1",
|
"range-parser": "~1.2.1",
|
||||||
@@ -7095,9 +7124,9 @@
|
|||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
"nanoid": {
|
"nanoid": {
|
||||||
"version": "3.3.6",
|
"version": "3.3.8",
|
||||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz",
|
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz",
|
||||||
"integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==",
|
"integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"negotiator": {
|
"negotiator": {
|
||||||
@@ -7184,9 +7213,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"path-to-regexp": {
|
"path-to-regexp": {
|
||||||
"version": "0.1.10",
|
"version": "0.1.12",
|
||||||
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz",
|
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz",
|
||||||
"integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w=="
|
"integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ=="
|
||||||
},
|
},
|
||||||
"pathe": {
|
"pathe": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
|
|||||||
@@ -6,6 +6,8 @@
|
|||||||
"@testing-library/jest-dom": "^5.16.5",
|
"@testing-library/jest-dom": "^5.16.5",
|
||||||
"@testing-library/react": "^13.4.0",
|
"@testing-library/react": "^13.4.0",
|
||||||
"@testing-library/user-event": "^14.4.3",
|
"@testing-library/user-event": "^14.4.3",
|
||||||
|
"@xterm/addon-fit": "^0.10.0",
|
||||||
|
"@xterm/xterm": "^5.5.0",
|
||||||
"express": "^4.21.1",
|
"express": "^4.21.1",
|
||||||
"guacamole-common-js": "^1.5.0",
|
"guacamole-common-js": "^1.5.0",
|
||||||
"http-proxy-middleware": "^3.0.3",
|
"http-proxy-middleware": "^3.0.3",
|
||||||
|
|||||||
@@ -22,7 +22,6 @@
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
border-radius: 5px;
|
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,7 +62,7 @@
|
|||||||
.hide-sidebar-button {
|
.hide-sidebar-button {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
bottom: 10px;
|
bottom: 10px;
|
||||||
right: 25px;
|
right: 23px;
|
||||||
background-color: rgb(108, 108, 108);
|
background-color: rgb(108, 108, 108);
|
||||||
color: white;
|
color: white;
|
||||||
border: none;
|
border: none;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import React, { useEffect, useRef, useState } from 'react';
|
import React, { useEffect, useRef, useState } from 'react';
|
||||||
import { Terminal } from 'xterm';
|
import { Terminal } from '@xterm/xterm';
|
||||||
import 'xterm/css/xterm.css';
|
import 'xterm/css/xterm.css';
|
||||||
import { FitAddon } from 'xterm-addon-fit';
|
import { FitAddon } from '@xterm/addon-fit';
|
||||||
import './App.css';
|
import './App.css';
|
||||||
|
|
||||||
const App = () => {
|
const App = () => {
|
||||||
@@ -10,98 +10,109 @@ const App = () => {
|
|||||||
const fitAddon = useRef(null);
|
const fitAddon = useRef(null);
|
||||||
const socket = useRef(null);
|
const socket = useRef(null);
|
||||||
const [host, setHost] = useState('');
|
const [host, setHost] = useState('');
|
||||||
|
const [port, setPort] = useState('22');
|
||||||
const [username, setUsername] = useState('');
|
const [username, setUsername] = useState('');
|
||||||
const [password, setPassword] = useState('');
|
const [password, setPassword] = useState('');
|
||||||
const [isConnected, setIsConnected] = useState(false);
|
const [isConnected, setIsConnected] = useState(false);
|
||||||
const [isSideBarHidden, setIsSideBarHidden] = useState(false);
|
const [isSideBarHidden, setIsSideBarHidden] = useState(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
console.log('Initializing terminal...');
|
|
||||||
terminal.current = new Terminal({
|
terminal.current = new Terminal({
|
||||||
cursorBlink: true,
|
cursorBlink: true,
|
||||||
theme: { background: '#1e1e1e', foreground: '#ffffff' },
|
theme: {
|
||||||
|
background: '#1e1e1e',
|
||||||
|
foreground: '#ffffff',
|
||||||
|
},
|
||||||
macOptionIsMeta: true,
|
macOptionIsMeta: true,
|
||||||
allowProposedApi: true,
|
allowProposedApi: true,
|
||||||
fontSize: 14,
|
scrollback: 5000,
|
||||||
});
|
});
|
||||||
|
|
||||||
fitAddon.current = new FitAddon();
|
fitAddon.current = new FitAddon();
|
||||||
terminal.current.loadAddon(fitAddon.current);
|
terminal.current.loadAddon(fitAddon.current);
|
||||||
|
|
||||||
if (terminalRef.current) {
|
terminal.current.open(terminalRef.current);
|
||||||
terminal.current.open(terminalRef.current);
|
fitAddon.current.fit();
|
||||||
console.log('Terminal opened successfully.');
|
|
||||||
} else {
|
|
||||||
console.error('Terminal reference is not valid!');
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// Fit the terminal and send the size when needed
|
||||||
|
const fitAndNotifyResize = () => {
|
||||||
|
fitAddon.current.fit();
|
||||||
|
if (socket.current && socket.current.readyState === WebSocket.OPEN) {
|
||||||
|
socket.current.send(JSON.stringify({
|
||||||
|
cols: terminal.current.cols,
|
||||||
|
rows: terminal.current.rows,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
window.addEventListener('resize', fitAndNotifyResize);
|
||||||
|
|
||||||
|
terminal.current.onResize(({ cols, rows }) => {
|
||||||
|
console.log(`Terminal resized to cols:${cols}, rows:${rows}`);
|
||||||
|
fitAndNotifyResize();
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleConnectionEstablished = () => {
|
||||||
|
fitAndNotifyResize();
|
||||||
|
};
|
||||||
|
|
||||||
|
window.addEventListener('connection-established', handleConnectionEstablished);
|
||||||
|
|
||||||
|
// Monitor terminal data (activity)
|
||||||
terminal.current.onData((data) => {
|
terminal.current.onData((data) => {
|
||||||
if (socket.current && socket.current.readyState === WebSocket.OPEN) {
|
if (socket.current && socket.current.readyState === WebSocket.OPEN) {
|
||||||
socket.current.send(data);
|
socket.current.send(data);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const resizeTerminal = () => {
|
|
||||||
if (terminalRef.current) {
|
|
||||||
fitAddon.current.fit();
|
|
||||||
notifyServerOfResize();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const notifyServerOfResize = () => {
|
|
||||||
if (socket.current && socket.current.readyState === WebSocket.OPEN) {
|
|
||||||
const { rows, cols } = terminal.current;
|
|
||||||
socket.current.send(
|
|
||||||
JSON.stringify({
|
|
||||||
type: 'resize',
|
|
||||||
rows,
|
|
||||||
cols,
|
|
||||||
height: terminalRef.current.offsetHeight,
|
|
||||||
width: terminalRef.current.offsetWidth,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
resizeTerminal();
|
|
||||||
window.addEventListener('resize', resizeTerminal);
|
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
terminal.current.dispose();
|
terminal.current.dispose();
|
||||||
if (socket.current) {
|
if (socket.current) {
|
||||||
socket.current.close();
|
socket.current.close();
|
||||||
}
|
}
|
||||||
window.removeEventListener('resize', resizeTerminal);
|
window.removeEventListener('resize', fitAndNotifyResize);
|
||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const handleConnect = () => {
|
const handleConnect = () => {
|
||||||
console.log('Connecting...');
|
|
||||||
const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
|
const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
|
||||||
const wsUrl = `${protocol}//${window.location.host}/ws/`;
|
const wsUrl = `${protocol}//${window.location.host}/ws/`; // Use current host and "/ws/" endpoint
|
||||||
console.log(`WebSocket URL: ${wsUrl}`);
|
|
||||||
|
if (!host || !username || !password) {
|
||||||
|
terminal.current.writeln('Please fill in all fields.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
socket.current = new WebSocket(wsUrl);
|
socket.current = new WebSocket(wsUrl);
|
||||||
|
|
||||||
socket.current.onopen = () => {
|
socket.current.onopen = () => {
|
||||||
console.log('WebSocket connection opened');
|
|
||||||
terminal.current.writeln(`Connected to WebSocket server at ${wsUrl}`);
|
terminal.current.writeln(`Connected to WebSocket server at ${wsUrl}`);
|
||||||
socket.current.send(JSON.stringify({ host, username, password }));
|
socket.current.send(
|
||||||
|
JSON.stringify({
|
||||||
|
host,
|
||||||
|
port,
|
||||||
|
username,
|
||||||
|
password,
|
||||||
|
rows: terminal.current.rows,
|
||||||
|
cols: terminal.current.cols
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
// Dispatch a custom event when connection is open
|
||||||
|
const event = new Event('connection-established');
|
||||||
|
window.dispatchEvent(event);
|
||||||
|
|
||||||
setIsConnected(true);
|
setIsConnected(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
socket.current.onmessage = (event) => {
|
socket.current.onmessage = (event) => {
|
||||||
console.log('Received message:', event.data);
|
|
||||||
terminal.current.write(event.data);
|
terminal.current.write(event.data);
|
||||||
};
|
};
|
||||||
|
|
||||||
socket.current.onerror = (error) => {
|
socket.current.onerror = (error) => {
|
||||||
console.error('WebSocket error:', error);
|
|
||||||
terminal.current.writeln(`WebSocket error: ${error.message}`);
|
terminal.current.writeln(`WebSocket error: ${error.message}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
socket.current.onclose = () => {
|
socket.current.onclose = () => {
|
||||||
console.log('WebSocket connection closed');
|
|
||||||
terminal.current.writeln('Disconnected from WebSocket server.');
|
terminal.current.writeln('Disconnected from WebSocket server.');
|
||||||
setIsConnected(false);
|
setIsConnected(false);
|
||||||
};
|
};
|
||||||
@@ -112,13 +123,33 @@ const App = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleSideBarHiding = () => {
|
const handleSideBarHiding = () => {
|
||||||
setIsSideBarHidden((prevState) => !prevState);
|
setIsSideBarHidden((prevState) => {
|
||||||
if (!isSideBarHidden) {
|
const newState = !prevState;
|
||||||
setTimeout(() => {
|
if (newState) {
|
||||||
fitAddon.current.fit();
|
setTimeout(() => {
|
||||||
notifyServerOfResize();
|
// Add a delay to ensure layout settles before resize action
|
||||||
}, 100);
|
fitAddon.current.fit();
|
||||||
}
|
if (socket.current && socket.current.readyState === WebSocket.OPEN) {
|
||||||
|
socket.current.send(JSON.stringify({
|
||||||
|
cols: terminal.current.cols,
|
||||||
|
rows: terminal.current.rows,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}, 100); // Delay of 100 milliseconds
|
||||||
|
} else {
|
||||||
|
setTimeout(() => {
|
||||||
|
// Refit terminal when showing sidebar as well
|
||||||
|
fitAddon.current.fit();
|
||||||
|
if (socket.current && socket.current.readyState === WebSocket.OPEN) {
|
||||||
|
socket.current.send(JSON.stringify({
|
||||||
|
cols: terminal.current.cols,
|
||||||
|
rows: terminal.current.rows,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}, 100); // Delay of 100 milliseconds
|
||||||
|
}
|
||||||
|
return newState;
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -132,6 +163,12 @@ const App = () => {
|
|||||||
value={host}
|
value={host}
|
||||||
onChange={(e) => handleInputChange(e, setHost)}
|
onChange={(e) => handleInputChange(e, setHost)}
|
||||||
/>
|
/>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
placeholder="Port"
|
||||||
|
value={port}
|
||||||
|
onChange={(e) => handleInputChange(e, setPort)}
|
||||||
|
/>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
placeholder="Username"
|
placeholder="Username"
|
||||||
@@ -152,7 +189,11 @@ const App = () => {
|
|||||||
<div ref={terminalRef} className="terminal-container"></div>
|
<div ref={terminalRef} className="terminal-container"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button className="hide-sidebar-button" onClick={handleSideBarHiding}>
|
{/* Hide button always positioned in the bottom-right corner */}
|
||||||
|
<button
|
||||||
|
className="hide-sidebar-button"
|
||||||
|
onClick={handleSideBarHiding}
|
||||||
|
>
|
||||||
{isSideBarHidden ? '+' : '-'}
|
{isSideBarHidden ? '+' : '-'}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ body {
|
|||||||
sans-serif;
|
sans-serif;
|
||||||
-webkit-font-smoothing: antialiased;
|
-webkit-font-smoothing: antialiased;
|
||||||
-moz-osx-font-smoothing: grayscale;
|
-moz-osx-font-smoothing: grayscale;
|
||||||
overflow: hidden; /* Prevent scrolling */
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
code {
|
code {
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 49 KiB |
@@ -1,7 +1,7 @@
|
|||||||
// start.js
|
// start.js
|
||||||
const { spawn } = require('child_process');
|
const { spawn } = require('child_process');
|
||||||
|
|
||||||
const child = spawn('node', ["\"D:/Programming Projects/SSH-Project-JB/backend/server.js\""], {
|
const child = spawn('node', ["\"D:/Programming Projects/Termix/backend/server.js\""], {
|
||||||
stdio: 'inherit', // this is key for interactivity
|
stdio: 'inherit', // this is key for interactivity
|
||||||
shell: true, // use system shell
|
shell: true, // use system shell
|
||||||
});
|
});
|
||||||
|
|||||||
0
git_push.sh
Executable file → Normal file
11
info.txt
@@ -1,11 +1,2 @@
|
|||||||
Currently:
|
Currently:
|
||||||
Fix issue after nano where the input no longer goes down to the bottom.
|
Done for release!
|
||||||
Fix issue where SSH randomly disconnects
|
|
||||||
Post inital build.
|
|
||||||
|
|
||||||
Overall Features:
|
|
||||||
SSH/RDP(?)/VNC(?)
|
|
||||||
Split Screen & Tabs
|
|
||||||
ChatGPT/Ollama Stuff
|
|
||||||
SMTP(?)
|
|
||||||
Login Page
|
|
||||||
164
package-lock.json
generated
@@ -1,164 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "SSH-Project-JB",
|
|
||||||
"lockfileVersion": 2,
|
|
||||||
"requires": true,
|
|
||||||
"packages": {
|
|
||||||
"": {
|
|
||||||
"dependencies": {
|
|
||||||
"cross-env": "^7.0.3",
|
|
||||||
"xterm-addon-fit": "^0.8.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/cross-env": {
|
|
||||||
"version": "7.0.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz",
|
|
||||||
"integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==",
|
|
||||||
"dependencies": {
|
|
||||||
"cross-spawn": "^7.0.1"
|
|
||||||
},
|
|
||||||
"bin": {
|
|
||||||
"cross-env": "src/bin/cross-env.js",
|
|
||||||
"cross-env-shell": "src/bin/cross-env-shell.js"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=10.14",
|
|
||||||
"npm": ">=6",
|
|
||||||
"yarn": ">=1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/cross-spawn": {
|
|
||||||
"version": "7.0.6",
|
|
||||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
|
|
||||||
"integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
|
|
||||||
"dependencies": {
|
|
||||||
"path-key": "^3.1.0",
|
|
||||||
"shebang-command": "^2.0.0",
|
|
||||||
"which": "^2.0.1"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 8"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/isexe": {
|
|
||||||
"version": "2.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
|
|
||||||
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="
|
|
||||||
},
|
|
||||||
"node_modules/path-key": {
|
|
||||||
"version": "3.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
|
|
||||||
"integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=8"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/shebang-command": {
|
|
||||||
"version": "2.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
|
|
||||||
"integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
|
|
||||||
"dependencies": {
|
|
||||||
"shebang-regex": "^3.0.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=8"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/shebang-regex": {
|
|
||||||
"version": "3.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
|
|
||||||
"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=8"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/which": {
|
|
||||||
"version": "2.0.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
|
||||||
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
|
|
||||||
"dependencies": {
|
|
||||||
"isexe": "^2.0.0"
|
|
||||||
},
|
|
||||||
"bin": {
|
|
||||||
"node-which": "bin/node-which"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 8"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/xterm": {
|
|
||||||
"version": "5.3.0",
|
|
||||||
"license": "MIT",
|
|
||||||
"peer": true
|
|
||||||
},
|
|
||||||
"node_modules/xterm-addon-fit": {
|
|
||||||
"version": "0.8.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/xterm-addon-fit/-/xterm-addon-fit-0.8.0.tgz",
|
|
||||||
"integrity": "sha512-yj3Np7XlvxxhYF/EJ7p3KHaMt6OdwQ+HDu573Vx1lRXsVxOcnVJs51RgjZOouIZOczTsskaS+CpXspK81/DLqw==",
|
|
||||||
"deprecated": "This package is now deprecated. Move to @xterm/addon-fit instead.",
|
|
||||||
"peerDependencies": {
|
|
||||||
"xterm": "^5.0.0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"cross-env": {
|
|
||||||
"version": "7.0.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz",
|
|
||||||
"integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==",
|
|
||||||
"requires": {
|
|
||||||
"cross-spawn": "^7.0.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"cross-spawn": {
|
|
||||||
"version": "7.0.6",
|
|
||||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
|
|
||||||
"integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
|
|
||||||
"requires": {
|
|
||||||
"path-key": "^3.1.0",
|
|
||||||
"shebang-command": "^2.0.0",
|
|
||||||
"which": "^2.0.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"isexe": {
|
|
||||||
"version": "2.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
|
|
||||||
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="
|
|
||||||
},
|
|
||||||
"path-key": {
|
|
||||||
"version": "3.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
|
|
||||||
"integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="
|
|
||||||
},
|
|
||||||
"shebang-command": {
|
|
||||||
"version": "2.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
|
|
||||||
"integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
|
|
||||||
"requires": {
|
|
||||||
"shebang-regex": "^3.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"shebang-regex": {
|
|
||||||
"version": "3.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
|
|
||||||
"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="
|
|
||||||
},
|
|
||||||
"which": {
|
|
||||||
"version": "2.0.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
|
||||||
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
|
|
||||||
"requires": {
|
|
||||||
"isexe": "^2.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"xterm": {
|
|
||||||
"version": "5.3.0",
|
|
||||||
"peer": true
|
|
||||||
},
|
|
||||||
"xterm-addon-fit": {
|
|
||||||
"version": "0.8.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/xterm-addon-fit/-/xterm-addon-fit-0.8.0.tgz",
|
|
||||||
"integrity": "sha512-yj3Np7XlvxxhYF/EJ7p3KHaMt6OdwQ+HDu573Vx1lRXsVxOcnVJs51RgjZOouIZOczTsskaS+CpXspK81/DLqw==",
|
|
||||||
"requires": {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
{
|
|
||||||
"dependencies": {
|
|
||||||
"cross-env": "^7.0.3",
|
|
||||||
"xterm-addon-fit": "^0.8.0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
Before Width: | Height: | Size: 2.0 MiB |
|
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 4.2 KiB |
|
Before Width: | Height: | Size: 5.2 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 9.4 KiB After Width: | Height: | Size: 39 KiB |
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"short_name": "React App",
|
"short_name": "Termix",
|
||||||
"name": "Create React App Sample",
|
"name": "Termix",
|
||||||
"icons": [
|
"icons": [
|
||||||
{
|
{
|
||||||
"src": "favicon.ico",
|
"src": "favicon.ico",
|
||||||
|
|||||||
BIN
repo-images/DemoImage1.png
Normal file
|
After Width: | Height: | Size: 21 KiB |
BIN
repo-images/TermixLogo.png
Normal file
|
After Width: | Height: | Size: 19 KiB |