Release 1.0 #7

Merged
LukeGus merged 5 commits from main into release-1.0 2024-12-13 12:48:05 +11:00
37 changed files with 926 additions and 278 deletions
Showing only changes of commit 15e1fd215e - Show all commits

No files matched your search

-7
View File
@@ -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
View File
Whitespace-only changes.
-1
View File
@@ -1 +0,0 @@
{"Key":"unix:///var/run/docker.sock","Name":"","Global":false}
+32 -16
View File
@@ -1,4 +1,5 @@
name: Build and Push Docker Image
on:
push:
branches:
@@ -8,7 +9,7 @@ on:
tag_name:
description: "Custom tag name for the Docker image"
required: false
default: "development-latest"
default: ""
jobs:
build:
@@ -16,49 +17,64 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v2
- name: Setup Node.js
uses: actions/setup-node@v2
with:
node-version: '18'
- name: Install Dependencies and Build Frontend
run: |
cd frontend
npm install
npm ci
npm run build
- name: Setup Docker Buildx
uses: docker/setup-buildx-action@v1
- name: Set up QEMU
uses: docker/setup-qemu-action@v1
- name: Login to Docker Registry
uses: docker/login-action@v1
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Determine Docker image tag
run: |
echo "REPO_OWNER=$(echo ${{ github.repository_owner }} | tr '[:upper:]' '[:lower:]')" >> $GITHUB_ENV
if [ -n "${{ github.event.inputs.tag_name }}" ]; then
IMAGE_TAG="${{ github.event.inputs.tag_name }}"
if [ "${{ github.event.inputs.tag_name }}" == "" ]; then
IMAGE_TAG="${{ github.ref_name }}-development-latest"
else
IMAGE_TAG="development-latest"
IMAGE_TAG="${{ github.event.inputs.tag_name }}"
fi
echo "IMAGE_TAG=$IMAGE_TAG" >> $GITHUB_ENV
- name: Build and Push Docker Image
uses: docker/build-push-action@v2
with:
context: .
file: ./docker/Dockerfile
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 }}
- name: Cleanup Docker Images
run: docker image prune -af
- name: Notify via ntfy
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
View File
@@ -133,6 +133,8 @@ yarn-error.log*
.sudo_as_admin_successful
.wget-hsts
.git-credentials
.docker/
.bash_logout
# VSCode Files
.vscode-server/
+8
View File
@@ -0,0 +1,8 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml
Generated
+1
View File
@@ -0,0 +1 @@
Termix
+12
View 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
View File
@@ -0,0 +1 @@
<svg id="svg" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="400" height="400" viewBox="0, 0, 400,400"><g id="svgg"><path id="path0" d="M108.560 88.160 L 107.200 89.520 107.201 119.660 C 107.203 148.684,107.231 149.847,107.972 151.060 C 109.081 152.881,111.184 153.202,121.920 153.190 C 135.693 153.176,135.650 153.198,136.013 146.043 C 136.374 138.941,137.344 138.000,144.307 138.000 C 151.310 138.000,151.195 138.326,151.198 118.589 C 151.200 102.368,151.159 102.662,153.604 101.398 C 155.225 100.559,162.787 100.566,164.413 101.407 C 166.995 102.742,166.800 93.928,166.800 209.193 C 166.800 322.394,166.676 315.827,168.847 317.348 C 170.271 318.345,229.729 318.345,231.153 317.348 C 233.324 315.827,233.200 322.394,233.200 209.193 C 233.200 93.928,233.005 102.742,235.587 101.407 C 237.475 100.431,245.006 100.562,246.710 101.602 C 248.732 102.834,248.799 103.372,248.817 118.526 C 248.842 138.302,248.736 138.000,255.662 138.000 C 262.571 138.000,263.622 139.047,263.990 146.298 C 264.338 153.153,264.385 153.176,278.080 153.190 C 288.816 153.202,290.919 152.881,292.028 151.060 C 292.769 149.847,292.797 148.684,292.799 119.660 L 292.800 89.520 291.440 88.160 L 290.080 86.800 200.000 86.800 L 109.920 86.800 108.560 88.160 " stroke="none" fill="#dbdbdb" fill-rule="evenodd"></path><path id="path1" d="M187.600 5.600 C 187.600 5.841,185.941 6.000,183.424 6.000 C 181.071 6.000,179.139 6.175,179.000 6.400 C 178.864 6.620,177.334 6.800,175.600 6.800 C 173.866 6.800,172.336 6.980,172.200 7.200 C 172.064 7.420,170.894 7.600,169.600 7.600 C 168.306 7.600,167.136 7.780,167.000 8.000 C 166.864 8.220,165.874 8.400,164.800 8.400 C 163.726 8.400,162.736 8.580,162.600 8.800 C 162.464 9.020,161.553 9.200,160.576 9.200 C 159.599 9.200,158.800 9.380,158.800 9.600 C 158.800 9.820,158.001 10.000,157.024 10.000 C 156.047 10.000,155.148 10.161,155.026 10.358 C 154.818 10.695,154.258 10.817,150.100 11.432 C 149.165 11.571,148.400 11.845,148.400 12.042 C 148.400 12.239,147.860 12.400,147.200 12.400 C 146.540 12.400,146.000 12.580,146.000 12.800 C 146.000 13.020,145.280 13.200,144.400 13.200 C 143.520 13.200,142.800 13.380,142.800 13.600 C 142.800 13.820,142.361 14.000,141.824 14.000 C 141.287 14.000,140.736 14.180,140.600 14.400 C 140.464 14.620,139.924 14.800,139.400 14.800 C 138.876 14.800,138.336 14.980,138.200 15.200 C 138.064 15.420,137.423 15.600,136.776 15.600 C 136.129 15.600,135.600 15.780,135.600 16.000 C 135.600 16.220,135.060 16.400,134.400 16.400 C 133.740 16.400,133.200 16.580,133.200 16.800 C 133.200 17.020,132.840 17.200,132.400 17.200 C 131.960 17.200,131.600 17.380,131.600 17.600 C 131.600 17.820,131.060 18.000,130.400 18.000 C 129.740 18.000,129.200 18.180,129.200 18.400 C 129.200 18.620,128.761 18.800,128.224 18.800 C 127.687 18.800,127.136 18.980,127.000 19.200 C 126.864 19.420,126.403 19.600,125.976 19.600 C 125.549 19.600,125.200 19.780,125.200 20.000 C 125.200 20.220,124.858 20.400,124.441 20.400 C 124.023 20.400,122.655 20.940,121.400 21.600 C 120.145 22.260,118.867 22.800,118.559 22.800 C 118.252 22.800,118.000 22.980,118.000 23.200 C 118.000 23.420,117.671 23.600,117.268 23.600 C 116.238 23.600,112.755 25.421,113.108 25.775 C 113.269 25.935,113.220 26.030,113.000 25.986 C 112.070 25.798,111.299 26.049,110.492 26.800 C 110.020 27.240,109.482 27.600,109.296 27.600 C 108.703 27.600,106.806 28.589,106.803 28.900 C 106.801 29.065,106.440 29.200,106.000 29.200 C 105.560 29.200,105.200 29.380,105.200 29.600 C 105.200 29.820,104.840 30.000,104.400 30.000 C 103.960 30.000,103.600 30.180,103.600 30.400 C 103.600 30.620,103.364 30.800,103.075 30.800 C 102.787 30.800,102.164 31.160,101.692 31.600 C 101.220 32.040,100.638 32.400,100.400 32.400 C 100.162 32.400,99.580 32.760,99.108 33.200 C 98.636 33.640,98.013 34.000,97.725 34.000 C 97.436 34.000,97.200 34.180,97.200 34.400 C 97.200 34.620,97.010 34.800,96.778 34.800 C 96.546 34.800,95.296 35.520,94.000 36.400 C 92.704 37.280,91.454 38.000,91.222 38.000 C 90.990 38.000,90.800 38.180,90.800 38.400 C 90.800 38.620,90.557 38.800,90.259 38.800 C 89.962 38.800,89.154 39.340,88.463 40.000 C 87.772 40.660,86.975 41.200,86.692 41.200 C 86.409 41.200,85.917 41.560,85.600 42.000 C 85.283 42.440,84.831 42.800,84.596 42.800 C 84.360 42.800,83.372 43.520,82.400 44.400 C 81.428 45.280,80.472 46.000,80.276 46.000 C 80.081 46.000,79.417 46.540,78.800 47.200 C 78.183 47.860,77.526 48.401,77.340 48.402 C 77.153 48.403,75.871 49.483,74.492 50.802 C 73.113 52.121,71.805 53.200,71.587 53.200 C 71.077 53.200,54.000 70.348,54.000 70.860 C 54.000 71.071,52.920 72.304,51.600 73.600 C 50.280 74.896,49.200 76.145,49.200 76.377 C 49.200 76.609,48.480 77.541,47.600 78.448 C 46.720 79.355,46.000 80.273,46.000 80.488 C 46.000 80.703,45.505 81.356,44.900 81.940 C 44.295 82.523,43.545 83.495,43.232 84.100 C 42.920 84.705,42.515 85.200,42.332 85.200 C 42.150 85.200,42.000 85.443,42.000 85.741 C 42.000 86.038,41.460 86.846,40.800 87.537 C 40.140 88.228,39.600 88.Line truncated

After

Width:  |  Height:  |  Size: 47 KiB

+8
View File
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/Termix.iml" filepath="$PROJECT_DIR$/.idea/Termix.iml" />
</modules>
</component>
</project>
Generated
+6
View File
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>
+455
View File
@@ -0,0 +1,455 @@
<?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 web-socket timeout." />
<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">{
&quot;lastFilter&quot;: {}
}</component>
<component name="GithubPullRequestsUISettings"><![CDATA[{
"selectedUrlAndAccountId": {
"url": "https://github.com/LukeGus/Termix",
"accountId": "f107d505-1915-4c73-a3f4-e0440737e1dc"
}
}]]></component>
<component name="ProjectColorInfo">{
&quot;customColor&quot;: &quot;636378de&quot;,
&quot;associatedIndex&quot;: 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"><![CDATA[{
"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 &quot;powershell&quot; -ArgumentList &quot;-NoProfile&quot;, &quot;-Command npm run start-vite&quot;; Start-Process &quot;powershell&quot; -ArgumentList &quot;-NoProfile&quot;, &quot;-Command npm run start-server&quot; " />
<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="npm.run_start_frontend" />
<item itemvalue="Shell Script.run_backend_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="2933000" />
</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 &amp; 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 &amp; 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 &amp; 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>
<option name="localTasksCounter" value="35" />
<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="Full return back to old code with minor fixes" />
<MESSAGE value="Terminal size fix #18 (rows &amp; cols fix)" />
<MESSAGE value="Test ntfy build notification system" />
<MESSAGE value="Silent resize cmds &amp; Auto resize terminal #1" />
<MESSAGE value="Silent resize cmds &amp; 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." />
<option name="LAST_COMMIT_MESSAGE" value="Fix web-socket timeout." />
</component>
</project>
+21
View 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.
+49 -1
View File
@@ -1 +1,49 @@
SSH is silly
# Repo Stats
![GitHub Repo stars](https://img.shields.io/github/stars/LukeGus/Termix?style=flat&label=Stars)
![GitHub forks](https://img.shields.io/github/forks/LukeGus/Termix?style=flat&label=Forks)
![GitHub Release](https://img.shields.io/github/v/release/LukeGus/Termix?style=flat&label=Release)
#### Top Technologies
[![React Badge](https://img.shields.io/badge/-React-61DBFB?style=flat-square&labelColor=black&logo=react&logoColor=61DBFB)](#)
[![Javascript Badge](https://img.shields.io/badge/-Javascript-F0DB4F?style=flat-square&labelColor=black&logo=javascript&logoColor=F0DB4F)](#)
[![Nodejs Badge](https://img.shields.io/badge/-Nodejs-3C873A?style=flat-square&labelColor=black&logo=node.js&logoColor=3C873A)](#)
[![HTML Badge](https://img.shields.io/badge/-HTML-E34F26?style=flat-square&labelColor=black&logo=html5&logoColor=E34F26)](#)
[![CSS Badge](https://img.shields.io/badge/-CSS-1572B6?style=flat-square&labelColor=black&logo=css3&logoColor=1572B6)](#)
[![Docker Badge](https://img.shields.io/badge/-Docker-2496ED?style=flat-square&labelColor=black&logo=docker&logoColor=2496ED)](#)
<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
![Demo Image](repo-images/DemoImage1.png)
# License
Distributed under the MIT license. See LICENSE for more information.
+51 -22
View File
@@ -11,6 +11,8 @@
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^14.4.3",
"@xterm/addon-fit": "^0.10.0",
"@xterm/xterm": "^5.5.0",
"express": "^4.21.1",
"guacamole-common-js": "^1.5.0",
"http-proxy-middleware": "^3.0.3",
@@ -1501,6 +1503,19 @@
"integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==",
"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": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz",
@@ -2288,10 +2303,9 @@
}
},
"node_modules/express": {
"version": "4.21.1",
"resolved": "https://registry.npmjs.org/express/-/express-4.21.1.tgz",
"integrity": "sha512-YSFlK1Ee0/GC8QaO91tHcDxJiE/X4FbpAyQWkxAvG6AXCuR65YzK8ua6D9hvi/TzUfZMpc+BwuM1IPw8fmQBiQ==",
"license": "MIT",
"version": "4.21.2",
"resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz",
"integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==",
"dependencies": {
"accepts": "~1.3.8",
"array-flatten": "1.1.1",
@@ -2312,7 +2326,7 @@
"methods": "~1.1.2",
"on-finished": "2.4.1",
"parseurl": "~1.3.3",
"path-to-regexp": "0.1.10",
"path-to-regexp": "0.1.12",
"proxy-addr": "~2.0.7",
"qs": "6.13.0",
"range-parser": "~1.2.1",
@@ -2327,6 +2341,10 @@
},
"engines": {
"node": ">= 0.10.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/express"
}
},
"node_modules/express/node_modules/debug": {
@@ -3394,9 +3412,9 @@
"optional": true
},
"node_modules/nanoid": {
"version": "3.3.6",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz",
"integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==",
"version": "3.3.8",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz",
"integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==",
"dev": true,
"funding": [
{
@@ -3404,6 +3422,7 @@
"url": "https://github.com/sponsors/ai"
}
],
"license": "MIT",
"bin": {
"nanoid": "bin/nanoid.cjs"
},
@@ -3539,10 +3558,9 @@
}
},
"node_modules/path-to-regexp": {
"version": "0.1.10",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz",
"integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==",
"license": "MIT"
"version": "0.1.12",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz",
"integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ=="
},
"node_modules/pathe": {
"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": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz",
@@ -6320,9 +6349,9 @@
}
},
"express": {
"version": "4.21.1",
"resolved": "https://registry.npmjs.org/express/-/express-4.21.1.tgz",
"integrity": "sha512-YSFlK1Ee0/GC8QaO91tHcDxJiE/X4FbpAyQWkxAvG6AXCuR65YzK8ua6D9hvi/TzUfZMpc+BwuM1IPw8fmQBiQ==",
"version": "4.21.2",
"resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz",
"integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==",
"requires": {
"accepts": "~1.3.8",
"array-flatten": "1.1.1",
@@ -6343,7 +6372,7 @@
"methods": "~1.1.2",
"on-finished": "2.4.1",
"parseurl": "~1.3.3",
"path-to-regexp": "0.1.10",
"path-to-regexp": "0.1.12",
"proxy-addr": "~2.0.7",
"qs": "6.13.0",
"range-parser": "~1.2.1",
@@ -7096,9 +7125,9 @@
"optional": true
},
"nanoid": {
"version": "3.3.6",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz",
"integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==",
"version": "3.3.8",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz",
"integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==",
"dev": true
},
"negotiator": {
@@ -7185,9 +7214,9 @@
"dev": true
},
"path-to-regexp": {
"version": "0.1.10",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz",
"integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w=="
"version": "0.1.12",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz",
"integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ=="
},
"pathe": {
"version": "1.1.1",
+3 -1
View File
@@ -6,6 +6,8 @@
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^14.4.3",
"@xterm/addon-fit": "^0.10.0",
"@xterm/xterm": "^5.5.0",
"express": "^4.21.1",
"guacamole-common-js": "^1.5.0",
"http-proxy-middleware": "^3.0.3",
@@ -55,4 +57,4 @@
"vite": "^4.5.5",
"vitest": "^0.34.6"
}
}
}
+83 -76
View File
@@ -2,97 +2,104 @@ const WebSocket = require('ws');
const ssh2 = require('ssh2');
const http = require('http');
// Create an HTTP server to serve WebSocket connections
const server = http.createServer((req, res) => {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('WebSocket server is running\n');
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('WebSocket server is running\n');
});
// Create a WebSocket server attached to the HTTP server
const wss = new WebSocket.Server({ server });
// WebSocket connection handling
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) => {
try {
const data = JSON.parse(message); // Try parsing the incoming message as JSON
// 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
const resizeTerminal = (cols, rows) => {
if (stream && stream.setWindow) {
stream.setWindow(rows, cols, rows * 100, cols * 100); // Adjust terminal size
console.log(`Terminal resized successfully: cols=${cols}, rows=${rows}`);
}
};
conn = new ssh2.Client(); // Create a new SSH connection instance
ws.on('message', (message) => {
const messageStr = message.toString();
// When the SSH connection is ready
conn.on('ready', () => {
console.log('SSH Connection established');
// Start an interactive shell session
conn.shell((err, stream) => {
if (err) {
console.log(`SSH Error: ${err}`);
ws.send(`Error: ${err}`);
return;
let data;
try {
if (messageStr.trim().startsWith('{')) {
data = JSON.parse(messageStr);
} else if (stream && stream.writable) {
stream.write(messageStr);
return;
}
// Handle data from SSH session
stream.on('data', (data) => {
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
} catch (error) {
console.error('Failed to process message:', error);
return;
}
} else {
console.error('SSH connection is not established yet.');
}
}
});
// Handle WebSocket close event
ws.on('close', () => {
console.log('WebSocket closed');
if (conn) {
conn.end(); // Close SSH connection when WebSocket client disconnects
}
});
if (data?.host && data.port && data.username && data.password) {
conn.on('ready', () => {
console.log('SSH Connection established');
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, () => {
console.log('WebSocket server is listening on ws://localhost:8081');
console.log('WebSocket server is listening on ws://localhost:8081');
});
Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

+3 -3
View File
@@ -2,12 +2,12 @@
<html lang="en">
<head>
<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="theme-color" content="#000000" />
<meta
name="description"
content="Web site created using @vitejs/plugin-react"
content="Sever management software for SSH!"
/>
<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/
-->
<link rel="manifest" href="/manifest.json" />
<title>React App</title>
<title>Termix</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
+51 -22
View File
@@ -11,6 +11,8 @@
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^14.4.3",
"@xterm/addon-fit": "^0.10.0",
"@xterm/xterm": "^5.5.0",
"express": "^4.21.1",
"guacamole-common-js": "^1.5.0",
"http-proxy-middleware": "^3.0.3",
@@ -1501,6 +1503,19 @@
"integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==",
"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": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz",
@@ -2288,10 +2303,9 @@
}
},
"node_modules/express": {
"version": "4.21.1",
"resolved": "https://registry.npmjs.org/express/-/express-4.21.1.tgz",
"integrity": "sha512-YSFlK1Ee0/GC8QaO91tHcDxJiE/X4FbpAyQWkxAvG6AXCuR65YzK8ua6D9hvi/TzUfZMpc+BwuM1IPw8fmQBiQ==",
"license": "MIT",
"version": "4.21.2",
"resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz",
"integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==",
"dependencies": {
"accepts": "~1.3.8",
"array-flatten": "1.1.1",
@@ -2312,7 +2326,7 @@
"methods": "~1.1.2",
"on-finished": "2.4.1",
"parseurl": "~1.3.3",
"path-to-regexp": "0.1.10",
"path-to-regexp": "0.1.12",
"proxy-addr": "~2.0.7",
"qs": "6.13.0",
"range-parser": "~1.2.1",
@@ -2327,6 +2341,10 @@
},
"engines": {
"node": ">= 0.10.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/express"
}
},
"node_modules/express/node_modules/debug": {
@@ -3394,9 +3412,9 @@
"optional": true
},
"node_modules/nanoid": {
"version": "3.3.6",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz",
"integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==",
"version": "3.3.8",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz",
"integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==",
"dev": true,
"funding": [
{
@@ -3404,6 +3422,7 @@
"url": "https://github.com/sponsors/ai"
}
],
"license": "MIT",
"bin": {
"nanoid": "bin/nanoid.cjs"
},
@@ -3539,10 +3558,9 @@
}
},
"node_modules/path-to-regexp": {
"version": "0.1.10",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz",
"integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==",
"license": "MIT"
"version": "0.1.12",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz",
"integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ=="
},
"node_modules/pathe": {
"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": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz",
@@ -6319,9 +6348,9 @@
}
},
"express": {
"version": "4.21.1",
"resolved": "https://registry.npmjs.org/express/-/express-4.21.1.tgz",
"integrity": "sha512-YSFlK1Ee0/GC8QaO91tHcDxJiE/X4FbpAyQWkxAvG6AXCuR65YzK8ua6D9hvi/TzUfZMpc+BwuM1IPw8fmQBiQ==",
"version": "4.21.2",
"resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz",
"integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==",
"requires": {
"accepts": "~1.3.8",
"array-flatten": "1.1.1",
@@ -6342,7 +6371,7 @@
"methods": "~1.1.2",
"on-finished": "2.4.1",
"parseurl": "~1.3.3",
"path-to-regexp": "0.1.10",
"path-to-regexp": "0.1.12",
"proxy-addr": "~2.0.7",
"qs": "6.13.0",
"range-parser": "~1.2.1",
@@ -7095,9 +7124,9 @@
"optional": true
},
"nanoid": {
"version": "3.3.6",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz",
"integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==",
"version": "3.3.8",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz",
"integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==",
"dev": true
},
"negotiator": {
@@ -7184,9 +7213,9 @@
"dev": true
},
"path-to-regexp": {
"version": "0.1.10",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz",
"integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w=="
"version": "0.1.12",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz",
"integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ=="
},
"pathe": {
"version": "1.1.1",
+3 -1
View File
@@ -6,6 +6,8 @@
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^14.4.3",
"@xterm/addon-fit": "^0.10.0",
"@xterm/xterm": "^5.5.0",
"express": "^4.21.1",
"guacamole-common-js": "^1.5.0",
"http-proxy-middleware": "^3.0.3",
@@ -24,7 +26,7 @@
},
"scripts": {
"start-vite": "cross-env BROWSER=none WDS_SOCKET_PORT=0 vite --port 8080",
"start-server": "node 'D:/Programming Projects/SSH-Project/ssh-project/backend/server.js'",
"start-server": "node ./start.js",
"start": "npm run start-vite && npm run start-server",
"build": "vite build",
"preview": "vite preview",
+1 -2
View File
@@ -22,7 +22,6 @@
flex-direction: column;
align-items: flex-start;
justify-content: space-between;
border-radius: 5px;
position: relative;
}
@@ -63,7 +62,7 @@
.hide-sidebar-button {
position: fixed;
bottom: 10px;
right: 10px;
right: 23px;
background-color: rgb(108, 108, 108);
color: white;
border: none;
+119 -69
View File
@@ -1,7 +1,7 @@
import React, { useEffect, useRef, useState } from 'react';
import { Terminal } from 'xterm';
import { Terminal } from '@xterm/xterm';
import 'xterm/css/xterm.css';
import { FitAddon } from 'xterm-addon-fit';
import { FitAddon } from '@xterm/addon-fit';
import './App.css';
const App = () => {
@@ -10,13 +10,13 @@ const App = () => {
const fitAddon = useRef(null);
const socket = useRef(null);
const [host, setHost] = useState('');
const [port, setPort] = useState('22');
const [username, setUsername] = useState('');
const [password, setPassword] = useState('');
const [isConnected, setIsConnected] = useState(false);
const [isSideBarHidden, setIsSideBarHidden] = useState(false);
useEffect(() => {
// Initialize the terminal and the fit addon
terminal.current = new Terminal({
cursorBlink: true,
theme: {
@@ -25,23 +25,37 @@ const App = () => {
},
macOptionIsMeta: true,
allowProposedApi: true,
scrollback: 1000, // Allow scrollback so the terminal doesn't lose state
scrollback: 5000,
});
// Initialize and attach the fit addon to the terminal
fitAddon.current = new FitAddon();
terminal.current.loadAddon(fitAddon.current);
terminal.current.open(terminalRef.current);
// Resize terminal to fit the container initially
fitAddon.current.fit();
// Adjust terminal size on window resize
const resizeListener = () => {
// 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', resizeListener);
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) => {
@@ -50,50 +64,54 @@ const App = () => {
}
});
// Add specific resize call for certain programs like nano or vim
const resizeTerminalOnStart = () => {
// Resize immediately after starting vim/nano or other programs
fitAddon.current.fit();
terminal.current.clear();
};
terminal.current.onData((data) => {
if (data.includes('nano') || data.includes('vim')) {
// Trigger resize immediately when these programs start
resizeTerminalOnStart();
}
});
// Cleanup on component unmount
return () => {
terminal.current.dispose();
if (socket.current) {
socket.current.close();
}
window.removeEventListener('resize', resizeListener);
window.removeEventListener('resize', fitAndNotifyResize);
};
}, []);
const handleConnect = () => {
const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
const wsUrl = `${protocol}//${window.location.host}/ws/`; // Use current host and "/ws/" endpoint
socket.current = new WebSocket(wsUrl);
if (!host || !username || !password) {
terminal.current.writeln('Please fill in all fields.');
return;
}
socket.current = new WebSocket("ws://localhost:8081");
socket.current.onopen = () => {
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);
};
socket.current.onmessage = (event) => {
terminal.current.write(event.data);
};
socket.current.onerror = (error) => {
terminal.current.writeln(`WebSocket error: ${error.message}`);
};
socket.current.onclose = () => {
terminal.current.writeln('Disconnected from WebSocket server.');
setIsConnected(false);
@@ -105,48 +123,80 @@ const App = () => {
};
const handleSideBarHiding = () => {
setIsSideBarHidden((prevState) => !prevState);
setIsSideBarHidden((prevState) => {
const newState = !prevState;
if (newState) {
setTimeout(() => {
// Add a delay to ensure layout settles before resize action
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 (
<div className="app-container">
<div className="main-content">
<div className={`sidebar ${isSideBarHidden ? 'hidden' : ''}`}>
<h2>Connection Details</h2>
<input
type="text"
placeholder="Host"
value={host}
onChange={(e) => handleInputChange(e, setHost)}
/>
<input
type="text"
placeholder="Username"
value={username}
onChange={(e) => handleInputChange(e, setUsername)}
/>
<input
type="password"
placeholder="Password"
value={password}
onChange={(e) => handleInputChange(e, setPassword)}
/>
<button onClick={handleConnect} disabled={isConnected}>
{isConnected ? 'Connected' : 'Start Session'}
</button>
<div className="app-container">
<div className="main-content">
<div className={`sidebar ${isSideBarHidden ? 'hidden' : ''}`}>
<h2>Connection Details</h2>
<input
type="text"
placeholder="Host"
value={host}
onChange={(e) => handleInputChange(e, setHost)}
/>
<input
type="text"
placeholder="Port"
value={port}
onChange={(e) => handleInputChange(e, setPort)}
/>
<input
type="text"
placeholder="Username"
value={username}
onChange={(e) => handleInputChange(e, setUsername)}
/>
<input
type="password"
placeholder="Password"
value={password}
onChange={(e) => handleInputChange(e, setPassword)}
/>
<button onClick={handleConnect} disabled={isConnected}>
{isConnected ? 'Connected' : 'Start Session'}
</button>
</div>
<div ref={terminalRef} className="terminal-container"></div>
</div>
<div ref={terminalRef} className="terminal-container"></div>
{/* Hide button always positioned in the bottom-right corner */}
<button
className="hide-sidebar-button"
onClick={handleSideBarHiding}
>
{isSideBarHidden ? '+' : '-'}
</button>
</div>
{/* Hide button always positioned in the bottom-right corner */}
<button
className="hide-sidebar-button"
onClick={handleSideBarHiding}
>
{isSideBarHidden ? '+' : '-'}
</button>
</div>
);
};
+1 -1
View File
@@ -5,7 +5,7 @@ body {
sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
overflow: hidden; /* Prevent scrolling */
overflow: hidden;
}
code {
+1 -1
View File
@@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 841.9 595.3"><g fill="#61DAFB"><path d="M666.3 296.5c0-32.5-40.7-63.3-103.1-82.4 14.4-63.6 8-114.2-20.2-130.4-6.5-3.8-14.1-5.6-22.4-5.6v22.3c4.6 0 8.3.9 11.4 2.6 13.6 7.8 19.5 37.5 14.9 75.7-1.1 9.4-2.9 19.3-5.1 29.4-19.6-4.8-41-8.5-63.5-10.9-13.5-18.5-27.5-35.3-41.6-50 32.6-30.3 63.2-46.9 84-46.9V78c-27.5 0-63.5 19.6-99.9 53.6-36.4-33.8-72.4-53.2-99.9-53.2v22.3c20.7 0 51.4 16.5 84 46.6-14 14.7-28 31.4-41.3 49.9-22.6 2.4-44 6.1-63.6 11-2.3-10-4-19.7-5.2-29-4.7-38.2 1.1-67.9 14.6-75.8 3-1.8 6.9-2.6 11.5-2.6V78.5c-8.4 0-16 1.8-22.6 5.6-28.1 16.2-34.4 66.7-19.9 130.1-62.2 19.2-102.7 49.9-102.7 82.3 0 32.5 40.7 63.3 103.1 82.4-14.4 63.6-8 114.2 20.2 130.4 6.5 3.8 14.1 5.6 22.5 5.6 27.5 0 63.5-19.6 99.9-53.6 36.4 33.8 72.4 53.2 99.9 53.2 8.4 0 16-1.8 22.6-5.6 28.1-16.2 34.4-66.7 19.9-130.1 62-19.1 102.5-49.9 102.5-82.3zm-130.2-66.7c-3.7 12.9-8.3 26.2-13.5 39.5-4.1-8-8.4-16-13.1-24-4.6-8-9.5-15.8-14.4-23.4 14.2 2.1 27.9 4.7 41 7.9zm-45.8 106.5c-7.8 13.5-15.8 26.3-24.1 38.2-14.9 1.3-30 2-45.2 2-15.1 0-30.2-.7-45-1.9-8.3-11.9-16.4-24.6-24.2-38-7.6-13.1-14.5-26.4-20.8-39.8 6.2-13.4 13.2-26.8 20.7-39.9 7.8-13.5 15.8-26.3 24.1-38.2 14.9-1.3 30-2 45.2-2 15.1 0 30.2.7 45 1.9 8.3 11.9 16.4 24.6 24.2 38 7.6 13.1 14.5 26.4 20.8 39.8-6.3 13.4-13.2 26.8-20.7 39.9zm32.3-13c5.4 13.4 10 26.8 13.8 39.8-13.1 3.2-26.9 5.9-41.2 8 4.9-7.7 9.8-15.6 14.4-23.7 4.6-8 8.9-16.1 13-24.1zM421.2 430c-9.3-9.6-18.6-20.3-27.8-32 9 .4 18.2.7 27.5.7 9.4 0 18.7-.2 27.8-.7-9 11.7-18.3 22.4-27.5 32zm-74.4-58.9c-14.2-2.1-27.9-4.7-41-7.9 3.7-12.9 8.3-26.2 13.5-39.5 4.1 8 8.4 16 13.1 24 4.7 8 9.5 15.8 14.4 23.4zM420.7 163c9.3 9.6 18.6 20.3 27.8 32-9-.4-18.2-.7-27.5-.7-9.4 0-18.7.2-27.8.7 9-11.7 18.3-22.4 27.5-32zm-74 58.9c-4.9 7.7-9.8 15.6-14.4 23.7-4.6 8-8.9 16-13 24-5.4-13.4-10-26.8-13.8-39.8 13.1-3.1 26.9-5.8 41.2-7.9zm-90.5 125.2c-35.4-15.1-58.3-34.9-58.3-50.6 0-15.7 22.9-35.6 58.3-50.6 8.6-3.7 18-7 27.7-10.1 5.7 19.6 13.2 40 22.5 60.9-9.2 20.8-16.6 41.1-22.2 60.6-9.9-3.1-19.3-6.5-28-10.2zM310 490c-13.6-7.8-19.5-37.5-14.9-75.7 1.1-9.4 2.9-19.3 5.1-29.4 19.6 4.8 41 8.5 63.5 10.9 13.5 18.5 27.5 35.3 41.6 50-32.6 30.3-63.2 46.9-84 46.9-4.5-.1-8.3-1-11.3-2.7zm237.2-76.2c4.7 38.2-1.1 67.9-14.6 75.8-3 1.8-6.9 2.6-11.5 2.6-20.7 0-51.4-16.5-84-46.6 14-14.7 28-31.4 41.3-49.9 22.6-2.4 44-6.1 63.6-11 2.3 10.1 4.1 19.8 5.2 29.1zm38.5-66.7c-8.6 3.7-18 7-27.7 10.1-5.7-19.6-13.2-40-22.5-60.9 9.2-20.8 16.6-41.1 22.2-60.6 9.9 3.1 19.3 6.5 28.1 10.2 35.4 15.1 58.3 34.9 58.3 50.6-.1 15.7-23 35.6-58.4 50.6zM320.8 78.4z"/><circle cx="420.9" cy="296.5" r="45.7"/><path d="M520.5 78.1z"/></g></svg>
<svg id="svg" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="400" height="400" viewBox="0, 0, 400,400"><g id="svgg"><path id="path0" d="M109.557 87.399 C 107.077 88.747,107.200 87.048,107.200 120.026 L 107.200 150.080 108.577 151.457 L 109.954 152.834 121.966 152.717 C 136.715 152.573,135.661 153.055,136.022 146.298 C 136.411 139.003,137.406 138.000,144.254 138.000 C 148.371 138.000,148.487 137.975,149.631 136.831 L 150.800 135.662 150.800 120.418 C 150.800 100.465,150.659 100.802,159.000 100.804 C 163.752 100.805,165.152 101.282,166.259 103.276 C 166.672 104.021,166.774 124.554,166.786 209.113 C 166.801 322.394,166.676 315.827,168.847 317.348 C 169.688 317.937,172.713 318.000,200.083 318.000 L 230.387 318.000 231.694 316.833 L 233.000 315.666 233.200 209.733 C 233.371 119.206,233.482 103.676,233.967 102.947 C 235.128 101.200,236.451 100.800,241.062 100.801 C 249.331 100.804,249.200 100.488,249.200 120.418 L 249.200 135.662 250.369 136.831 C 251.517 137.979,251.617 138.000,255.869 138.003 C 262.683 138.007,263.626 138.945,263.988 146.077 C 264.344 153.080,263.293 152.571,277.711 152.726 C 290.473 152.864,291.356 152.732,292.353 150.544 C 292.670 149.849,292.800 140.844,292.800 119.670 C 292.800 86.839,292.940 88.713,290.396 87.398 C 288.694 86.518,111.176 86.519,109.557 87.399 " stroke="none" fill="#dbdbdb" fill-rule="evenodd"></path><path id="path1" d="M188.000 5.600 C 188.000 5.840,186.408 6.000,184.024 6.000 C 181.804 6.000,179.938 6.177,179.800 6.400 C 179.664 6.620,177.943 6.800,175.976 6.800 C 173.859 6.800,172.400 6.963,172.400 7.200 C 172.400 7.420,171.421 7.600,170.224 7.600 C 169.027 7.600,167.936 7.780,167.800 8.000 C 167.664 8.220,166.674 8.400,165.600 8.400 C 164.526 8.400,163.524 8.599,163.374 8.843 C 163.183 9.151,162.996 9.121,162.756 8.743 C 162.567 8.444,162.409 8.389,162.406 8.621 C 162.403 8.852,161.746 9.060,160.947 9.083 C 160.148 9.105,159.383 9.293,159.247 9.499 C 159.111 9.705,158.371 9.827,157.601 9.770 C 156.832 9.713,155.957 9.870,155.656 10.119 C 155.356 10.368,154.505 10.520,153.765 10.456 C 153.025 10.393,152.190 10.488,151.910 10.668 C 151.208 11.118,147.996 11.961,146.900 11.982 C 146.405 11.992,146.000 12.180,146.000 12.400 C 146.000 12.620,145.608 12.800,145.128 12.800 C 144.256 12.800,141.577 13.617,141.200 13.998 C 140.966 14.234,140.013 14.495,139.300 14.518 C 139.025 14.526,138.800 14.694,138.800 14.890 C 138.800 15.087,138.665 15.168,138.500 15.071 C 138.335 14.973,137.750 15.080,137.200 15.306 C 136.650 15.533,135.961 15.768,135.669 15.829 C 135.377 15.889,134.837 16.070,134.469 16.231 C 134.101 16.391,133.350 16.596,132.800 16.686 C 132.250 16.776,131.740 17.018,131.667 17.225 C 131.593 17.431,131.188 17.600,130.767 17.600 C 130.345 17.600,130.000 17.780,130.000 18.000 C 130.000 18.220,129.550 18.400,129.000 18.400 C 128.450 18.400,128.000 18.547,128.000 18.728 C 128.000 18.908,127.100 19.300,126.000 19.600 C 124.900 19.900,124.000 20.292,124.000 20.472 C 124.000 20.653,123.651 20.800,123.224 20.800 C 122.797 20.800,122.336 20.980,122.200 21.200 C 122.064 21.420,121.503 21.600,120.953 21.600 C 120.388 21.600,120.060 21.774,120.200 22.000 C 120.348 22.240,119.836 22.402,118.924 22.406 C 117.793 22.411,117.555 22.512,118.000 22.800 C 118.468 23.102,118.357 23.189,117.500 23.194 C 116.895 23.197,116.400 23.380,116.400 23.600 C 116.400 23.820,116.122 24.000,115.783 24.000 C 115.444 24.000,114.780 24.360,114.308 24.800 C 113.836 25.240,113.134 25.600,112.748 25.600 C 112.363 25.600,111.936 25.780,111.800 26.000 C 111.664 26.220,111.203 26.400,110.776 26.400 C 110.349 26.400,110.000 26.591,110.000 26.824 C 110.000 27.057,109.820 27.136,109.600 27.000 C 109.380 26.864,109.200 27.011,109.200 27.326 C 109.200 27.644,108.620 28.036,107.900 28.206 C 107.185 28.374,106.510 28.541,106.400 28.577 C 105.688 28.808,102.081 31.186,101.056 32.100 C 100.377 32.705,99.504 33.200,99.115 33.200 C 98.470 33.200,97.574 33.780,96.184 35.100 C 95.894 35.375,95.483 35.600,95.271 35.600 C 95.058 35.600,94.307 36.140,93.600 36.800 C 92.893 37.460,91.968 38.000,91.544 38.000 C 91.120 38.000,90.139 38.634,89.364 39.409 C 88.589 40.185,87.785 40.714,87.577 40.586 C 87.370 40.458,87.200 40.543,87.200 40.776 C 87.200 41.009,86.942 41.200,86.627 41.200 C 86.312 41.200,85.939 41.563,85.798 42.006 C 85.657 42.449,85.390 42.717,85.203 42.602 C 85.017 42.487,84.601 42.656,84.280 42.977 C 83.958 43.299,83.605 43.472,83.495 43.361 C 83.384 43.251,82.452 43.890,81.423 44.780 C 80.393 45.671,79.388 46.400,79.188 46.400 C 78.989 46.400,78.940 46.700,79.081 47.066 C 79.252 47.513,79.183 47.636,78.868 47.442 C 78.611 47.283,78.400 47.343,78.400 47.576 C 78.400 47.809,78.170 48.000,77.888 48.000 C 77.607 48.000,77.117 48.360,76.800 48.800 C 76.483 49.240,75.983 49.600,75.688 49.600 C 75.394 49.600,75.251 49.759,75.371 49.954 C 75.491 50.148,75.054 50.529,74.400 50.800 C 73.746 51.071,73.309 51.452,73.429 51.646 C 73.549 51.841,73.470 52.000,73.254 52.000 C 73.Line truncated

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 49 KiB

+12
View File
@@ -0,0 +1,12 @@
// start.js
const { spawn } = require('child_process');
const child = spawn('node', ["\"D:/Programming Projects/Termix/backend/server.js\""], {
stdio: 'inherit', // this is key for interactivity
shell: true, // use system shell
});
child.on('exit', function (code, signal) {
console.log('child process exited with ' +
`code ${code} and signal ${signal}`);
});
Executable → Regular
View File
File mode changed.
+1 -10
View File
@@ -1,11 +1,2 @@
Currently:
Fix issue after nano where the input no longer goes down to the bottom.
Fix issue where SSH randomly disconnects
Post inital build.
Overall Features:
SSH/RDP(?)/VNC(?)
Split Screen & Tabs
ChatGPT/Ollama Stuff
SMTP(?)
Login Page
Done for release!
-38
View File
@@ -1,38 +0,0 @@
{
"name": "ssh-project",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"dependencies": {
"xterm-addon-fit": "^0.8.0"
}
},
"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": {
"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": {}
}
}
}
-5
View File
@@ -1,5 +0,0 @@
{
"dependencies": {
"xterm-addon-fit": "^0.8.0"
}
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.4 KiB

After

Width:  |  Height:  |  Size: 39 KiB

+2 -2
View File
@@ -1,6 +1,6 @@
{
"short_name": "React App",
"name": "Create React App Sample",
"short_name": "Termix",
"name": "Termix",
"icons": [
{
"src": "favicon.ico",
Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB