Compare commits

..

1 Commits

Author SHA1 Message Date
dependabot[bot]
b1c4063270 build(deps): bump v8-compile-cache from 2.3.0 to 2.4.0 in /app
Bumps [v8-compile-cache](https://github.com/zertosh/v8-compile-cache) from 2.3.0 to 2.4.0.
- [Changelog](https://github.com/zertosh/v8-compile-cache/blob/master/CHANGELOG.md)
- [Commits](https://github.com/zertosh/v8-compile-cache/compare/v2.3.0...v2.4.0)

---
updated-dependencies:
- dependency-name: v8-compile-cache
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-08-15 04:07:25 +00:00
121 changed files with 5096 additions and 8078 deletions

View File

@@ -1220,33 +1220,6 @@
"contributions": [ "contributions": [
"code" "code"
] ]
},
{
"login": "siebsie23",
"name": "Sibren",
"avatar_url": "https://avatars.githubusercontent.com/u/25083973?v=4",
"profile": "https://siebsie23.nl/",
"contributions": [
"code"
]
},
{
"login": "nwalser",
"name": "Nathaniel Walser",
"avatar_url": "https://avatars.githubusercontent.com/u/33339996?v=4",
"profile": "https://www.nathaniel-walser.com",
"contributions": [
"code"
]
},
{
"login": "aaronhuggins",
"name": "Aaron Huggins",
"avatar_url": "https://avatars.githubusercontent.com/u/16567111?v=4",
"profile": "https://github.com/aaronhuggins",
"contributions": [
"design"
]
} }
], ],
"contributorsPerLine": 7, "contributorsPerLine": 7,

1
.env
View File

@@ -1 +0,0 @@
# TABBY_CONFIG_DIRECTORY="PATH_TO_DIRECTORY"

View File

@@ -1,13 +1,7 @@
settings: settings:
import/parsers:
'@typescript-eslint/parser': ['.ts']
import/resolver: import/resolver:
typescript: typescript: true
project:
- tsconfig.json
- tabby-*/tsconfig.json
node: true node: true
env: env:
browser: true browser: true
es6: true es6: true
@@ -34,7 +28,7 @@ overrides:
- plugin:import/typescript - plugin:import/typescript
plugins: plugins:
- '@typescript-eslint' - '@typescript-eslint'
- import - 'import'
rules: rules:
'@typescript-eslint/semi': '@typescript-eslint/semi':
- error - error
@@ -136,7 +130,6 @@ overrides:
'@typescript-eslint/naming-convention': off '@typescript-eslint/naming-convention': off
'@typescript-eslint/lines-between-class-members': '@typescript-eslint/lines-between-class-members':
- error - error
- always
- exceptAfterSingleLine: true - exceptAfterSingleLine: true
'@typescript-eslint/dot-notation': off '@typescript-eslint/dot-notation': off
'@typescript-eslint/no-implicit-any-catch': off '@typescript-eslint/no-implicit-any-catch': off
@@ -159,6 +152,3 @@ overrides:
'@typescript-eslint/consistent-generic-constructors': off '@typescript-eslint/consistent-generic-constructors': off
'keyword-spacing': off 'keyword-spacing': off
'@typescript-eslint/keyword-spacing': off '@typescript-eslint/keyword-spacing': off
'@typescript-eslint/class-methods-use-this': off
'@typescript-eslint/lines-around-comment': off
'@typescript-eslint/no-redundant-type-constituents': off # broken

View File

@@ -2,7 +2,7 @@ name: Package-Build
on: [push, pull_request] on: [push, pull_request]
jobs: jobs:
Lint: Lint:
runs-on: ubuntu-20.04 runs-on: macos-11
steps: steps:
- name: Checkout - name: Checkout
@@ -31,7 +31,7 @@ jobs:
run: yarn run lint run: yarn run lint
macOS-Build: macOS-Build:
runs-on: macos-12 runs-on: macos-11
needs: Lint needs: Lint
strategy: strategy:
matrix: matrix:
@@ -53,8 +53,7 @@ jobs:
- name: Install deps - name: Install deps
run: | run: |
sudo -H pip install setuptools sudo npm i -g yarn@1.22.1
sudo npm i -g yarn@1.22.1 node-gyp@10
yarn --network-timeout 1000000 yarn --network-timeout 1000000
env: env:
ARCH: ${{matrix.arch}} ARCH: ${{matrix.arch}}
@@ -111,16 +110,16 @@ jobs:
- name: Package artifacts - name: Package artifacts
run: | run: |
mkdir artifact-dmg mkdir artifact-pkg
mv dist/*.dmg artifact-dmg/ mv dist/*.pkg artifact-pkg/
mkdir artifact-zip mkdir artifact-zip
mv dist/*.zip artifact-zip/ mv dist/*.zip artifact-zip/
- uses: actions/upload-artifact@master - uses: actions/upload-artifact@master
name: Upload DMG name: Upload PKG
with: with:
name: macOS .dmg (${{matrix.arch}}) name: macOS .pkg (${{matrix.arch}})
path: artifact-dmg path: artifact-pkg
- uses: actions/upload-artifact@master - uses: actions/upload-artifact@master
name: Upload ZIP name: Upload ZIP
@@ -163,7 +162,7 @@ jobs:
- name: Install deps (amd64) - name: Install deps (amd64)
run: | run: |
sudo apt-get update sudo apt-get update
sudo apt-get install libarchive-tools zsh python3-distutils sudo apt-get install libarchive-tools zsh
- name: Install npm_modules (amd64) - name: Install npm_modules (amd64)
run: | run: |

View File

@@ -327,11 +327,6 @@ Dank geht an diese wunderbaren Menschen ([emoji key](https://allcontributors.org
<td align="center" valign="top" width="14.28%"><a href="https://github.com/wljince007"><img src="https://avatars.githubusercontent.com/u/88243938?v=4?s=100" width="100px;" alt="wljince007"/><br /><sub><b>wljince007</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=wljince007" title="Code">💻</a></td> <td align="center" valign="top" width="14.28%"><a href="https://github.com/wljince007"><img src="https://avatars.githubusercontent.com/u/88243938?v=4?s=100" width="100px;" alt="wljince007"/><br /><sub><b>wljince007</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=wljince007" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/FeroTheFox"><img src="https://avatars.githubusercontent.com/u/52982404?v=4?s=100" width="100px;" alt="fero"/><br /><sub><b>fero</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=FeroTheFox" title="Code">💻</a></td> <td align="center" valign="top" width="14.28%"><a href="https://github.com/FeroTheFox"><img src="https://avatars.githubusercontent.com/u/52982404?v=4?s=100" width="100px;" alt="fero"/><br /><sub><b>fero</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=FeroTheFox" title="Code">💻</a></td>
</tr> </tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://siebsie23.nl/"><img src="https://avatars.githubusercontent.com/u/25083973?v=4?s=100" width="100px;" alt="Sibren"/><br /><sub><b>Sibren</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=siebsie23" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://www.nathaniel-walser.com"><img src="https://avatars.githubusercontent.com/u/33339996?v=4?s=100" width="100px;" alt="Nathaniel Walser"/><br /><sub><b>Nathaniel Walser</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=nwalser" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/aaronhuggins"><img src="https://avatars.githubusercontent.com/u/16567111?v=4?s=100" width="100px;" alt="Aaron Huggins"/><br /><sub><b>Aaron Huggins</b></sub></a><br /><a href="#design-aaronhuggins" title="Design">🎨</a></td>
</tr>
</tbody> </tbody>
</table> </table>

View File

@@ -329,11 +329,6 @@ Gracias a estas maravillosas personas ([emoji key](https://allcontributors.org/d
<td align="center" valign="top" width="14.28%"><a href="https://github.com/wljince007"><img src="https://avatars.githubusercontent.com/u/88243938?v=4?s=100" width="100px;" alt="wljince007"/><br /><sub><b>wljince007</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=wljince007" title="Code">💻</a></td> <td align="center" valign="top" width="14.28%"><a href="https://github.com/wljince007"><img src="https://avatars.githubusercontent.com/u/88243938?v=4?s=100" width="100px;" alt="wljince007"/><br /><sub><b>wljince007</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=wljince007" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/FeroTheFox"><img src="https://avatars.githubusercontent.com/u/52982404?v=4?s=100" width="100px;" alt="fero"/><br /><sub><b>fero</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=FeroTheFox" title="Code">💻</a></td> <td align="center" valign="top" width="14.28%"><a href="https://github.com/FeroTheFox"><img src="https://avatars.githubusercontent.com/u/52982404?v=4?s=100" width="100px;" alt="fero"/><br /><sub><b>fero</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=FeroTheFox" title="Code">💻</a></td>
</tr> </tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://siebsie23.nl/"><img src="https://avatars.githubusercontent.com/u/25083973?v=4?s=100" width="100px;" alt="Sibren"/><br /><sub><b>Sibren</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=siebsie23" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://www.nathaniel-walser.com"><img src="https://avatars.githubusercontent.com/u/33339996?v=4?s=100" width="100px;" alt="Nathaniel Walser"/><br /><sub><b>Nathaniel Walser</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=nwalser" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/aaronhuggins"><img src="https://avatars.githubusercontent.com/u/16567111?v=4?s=100" width="100px;" alt="Aaron Huggins"/><br /><sub><b>Aaron Huggins</b></sub></a><br /><a href="#design-aaronhuggins" title="Design">🎨</a></td>
</tr>
</tbody> </tbody>
</table> </table>

View File

@@ -326,11 +326,6 @@ Terima kasih kepada mereka yang telah membantu ([emoji key](https://allcontribut
<td align="center" valign="top" width="14.28%"><a href="https://github.com/wljince007"><img src="https://avatars.githubusercontent.com/u/88243938?v=4?s=100" width="100px;" alt="wljince007"/><br /><sub><b>wljince007</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=wljince007" title="Code">💻</a></td> <td align="center" valign="top" width="14.28%"><a href="https://github.com/wljince007"><img src="https://avatars.githubusercontent.com/u/88243938?v=4?s=100" width="100px;" alt="wljince007"/><br /><sub><b>wljince007</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=wljince007" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/FeroTheFox"><img src="https://avatars.githubusercontent.com/u/52982404?v=4?s=100" width="100px;" alt="fero"/><br /><sub><b>fero</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=FeroTheFox" title="Code">💻</a></td> <td align="center" valign="top" width="14.28%"><a href="https://github.com/FeroTheFox"><img src="https://avatars.githubusercontent.com/u/52982404?v=4?s=100" width="100px;" alt="fero"/><br /><sub><b>fero</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=FeroTheFox" title="Code">💻</a></td>
</tr> </tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://siebsie23.nl/"><img src="https://avatars.githubusercontent.com/u/25083973?v=4?s=100" width="100px;" alt="Sibren"/><br /><sub><b>Sibren</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=siebsie23" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://www.nathaniel-walser.com"><img src="https://avatars.githubusercontent.com/u/33339996?v=4?s=100" width="100px;" alt="Nathaniel Walser"/><br /><sub><b>Nathaniel Walser</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=nwalser" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/aaronhuggins"><img src="https://avatars.githubusercontent.com/u/16567111?v=4?s=100" width="100px;" alt="Aaron Huggins"/><br /><sub><b>Aaron Huggins</b></sub></a><br /><a href="#design-aaronhuggins" title="Design">🎨</a></td>
</tr>
</tbody> </tbody>
</table> </table>

View File

@@ -322,11 +322,6 @@ Grazie a queste persone meravigliose ([emoji key](https://allcontributors.org/do
<td align="center" valign="top" width="14.28%"><a href="https://github.com/wljince007"><img src="https://avatars.githubusercontent.com/u/88243938?v=4?s=100" width="100px;" alt="wljince007"/><br /><sub><b>wljince007</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=wljince007" title="Code">💻</a></td> <td align="center" valign="top" width="14.28%"><a href="https://github.com/wljince007"><img src="https://avatars.githubusercontent.com/u/88243938?v=4?s=100" width="100px;" alt="wljince007"/><br /><sub><b>wljince007</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=wljince007" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/FeroTheFox"><img src="https://avatars.githubusercontent.com/u/52982404?v=4?s=100" width="100px;" alt="fero"/><br /><sub><b>fero</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=FeroTheFox" title="Code">💻</a></td> <td align="center" valign="top" width="14.28%"><a href="https://github.com/FeroTheFox"><img src="https://avatars.githubusercontent.com/u/52982404?v=4?s=100" width="100px;" alt="fero"/><br /><sub><b>fero</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=FeroTheFox" title="Code">💻</a></td>
</tr> </tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://siebsie23.nl/"><img src="https://avatars.githubusercontent.com/u/25083973?v=4?s=100" width="100px;" alt="Sibren"/><br /><sub><b>Sibren</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=siebsie23" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://www.nathaniel-walser.com"><img src="https://avatars.githubusercontent.com/u/33339996?v=4?s=100" width="100px;" alt="Nathaniel Walser"/><br /><sub><b>Nathaniel Walser</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=nwalser" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/aaronhuggins"><img src="https://avatars.githubusercontent.com/u/16567111?v=4?s=100" width="100px;" alt="Aaron Huggins"/><br /><sub><b>Aaron Huggins</b></sub></a><br /><a href="#design-aaronhuggins" title="Design">🎨</a></td>
</tr>
</tbody> </tbody>
</table> </table>

View File

@@ -337,11 +337,6 @@ Windows上では、`Tabby.exe`がある場所と同じ場所に`data`フォル
<td align="center" valign="top" width="14.28%"><a href="https://github.com/wljince007"><img src="https://avatars.githubusercontent.com/u/88243938?v=4?s=100" width="100px;" alt="wljince007"/><br /><sub><b>wljince007</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=wljince007" title="Code">💻</a></td> <td align="center" valign="top" width="14.28%"><a href="https://github.com/wljince007"><img src="https://avatars.githubusercontent.com/u/88243938?v=4?s=100" width="100px;" alt="wljince007"/><br /><sub><b>wljince007</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=wljince007" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/FeroTheFox"><img src="https://avatars.githubusercontent.com/u/52982404?v=4?s=100" width="100px;" alt="fero"/><br /><sub><b>fero</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=FeroTheFox" title="Code">💻</a></td> <td align="center" valign="top" width="14.28%"><a href="https://github.com/FeroTheFox"><img src="https://avatars.githubusercontent.com/u/52982404?v=4?s=100" width="100px;" alt="fero"/><br /><sub><b>fero</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=FeroTheFox" title="Code">💻</a></td>
</tr> </tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://siebsie23.nl/"><img src="https://avatars.githubusercontent.com/u/25083973?v=4?s=100" width="100px;" alt="Sibren"/><br /><sub><b>Sibren</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=siebsie23" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://www.nathaniel-walser.com"><img src="https://avatars.githubusercontent.com/u/33339996?v=4?s=100" width="100px;" alt="Nathaniel Walser"/><br /><sub><b>Nathaniel Walser</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=nwalser" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/aaronhuggins"><img src="https://avatars.githubusercontent.com/u/16567111?v=4?s=100" width="100px;" alt="Aaron Huggins"/><br /><sub><b>Aaron Huggins</b></sub></a><br /><a href="#design-aaronhuggins" title="Design">🎨</a></td>
</tr>
</tbody> </tbody>
</table> </table>

View File

@@ -316,11 +316,6 @@ Pull requests and plugins are welcome!
<td align="center" valign="top" width="14.28%"><a href="https://github.com/wljince007"><img src="https://avatars.githubusercontent.com/u/88243938?v=4?s=100" width="100px;" alt="wljince007"/><br /><sub><b>wljince007</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=wljince007" title="Code">💻</a></td> <td align="center" valign="top" width="14.28%"><a href="https://github.com/wljince007"><img src="https://avatars.githubusercontent.com/u/88243938?v=4?s=100" width="100px;" alt="wljince007"/><br /><sub><b>wljince007</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=wljince007" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/FeroTheFox"><img src="https://avatars.githubusercontent.com/u/52982404?v=4?s=100" width="100px;" alt="fero"/><br /><sub><b>fero</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=FeroTheFox" title="Code">💻</a></td> <td align="center" valign="top" width="14.28%"><a href="https://github.com/FeroTheFox"><img src="https://avatars.githubusercontent.com/u/52982404?v=4?s=100" width="100px;" alt="fero"/><br /><sub><b>fero</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=FeroTheFox" title="Code">💻</a></td>
</tr> </tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://siebsie23.nl/"><img src="https://avatars.githubusercontent.com/u/25083973?v=4?s=100" width="100px;" alt="Sibren"/><br /><sub><b>Sibren</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=siebsie23" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://www.nathaniel-walser.com"><img src="https://avatars.githubusercontent.com/u/33339996?v=4?s=100" width="100px;" alt="Nathaniel Walser"/><br /><sub><b>Nathaniel Walser</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=nwalser" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/aaronhuggins"><img src="https://avatars.githubusercontent.com/u/16567111?v=4?s=100" width="100px;" alt="Aaron Huggins"/><br /><sub><b>Aaron Huggins</b></sub></a><br /><a href="#design-aaronhuggins" title="Design">🎨</a></td>
</tr>
</tbody> </tbody>
</table> </table>

View File

@@ -139,8 +139,6 @@ Plugins and themes can be installed directly from the Settings view inside Tabby
* [gruvbox](https://github.com/porkloin/terminus-theme-gruvbox) * [gruvbox](https://github.com/porkloin/terminus-theme-gruvbox)
* [windows10](https://www.npmjs.com/package/terminus-theme-windows10) * [windows10](https://www.npmjs.com/package/terminus-theme-windows10)
* [altair](https://github.com/yxuko/terminus-altair) * [altair](https://github.com/yxuko/terminus-altair)
* [catppuccin](https://github.com/catppuccin/tabby) - Soothing pastel theme for Tabby
* [noctis](https://github.com/aaronhuggins/tabby-colors-noctis) - color themes inspired by Noctis VS Code theme
# Sponsors <!-- omit in toc --> # Sponsors <!-- omit in toc -->
@@ -340,11 +338,6 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
<td align="center" valign="top" width="14.28%"><a href="https://github.com/wljince007"><img src="https://avatars.githubusercontent.com/u/88243938?v=4?s=100" width="100px;" alt="wljince007"/><br /><sub><b>wljince007</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=wljince007" title="Code">💻</a></td> <td align="center" valign="top" width="14.28%"><a href="https://github.com/wljince007"><img src="https://avatars.githubusercontent.com/u/88243938?v=4?s=100" width="100px;" alt="wljince007"/><br /><sub><b>wljince007</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=wljince007" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/FeroTheFox"><img src="https://avatars.githubusercontent.com/u/52982404?v=4?s=100" width="100px;" alt="fero"/><br /><sub><b>fero</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=FeroTheFox" title="Code">💻</a></td> <td align="center" valign="top" width="14.28%"><a href="https://github.com/FeroTheFox"><img src="https://avatars.githubusercontent.com/u/52982404?v=4?s=100" width="100px;" alt="fero"/><br /><sub><b>fero</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=FeroTheFox" title="Code">💻</a></td>
</tr> </tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://siebsie23.nl/"><img src="https://avatars.githubusercontent.com/u/25083973?v=4?s=100" width="100px;" alt="Sibren"/><br /><sub><b>Sibren</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=siebsie23" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://www.nathaniel-walser.com"><img src="https://avatars.githubusercontent.com/u/33339996?v=4?s=100" width="100px;" alt="Nathaniel Walser"/><br /><sub><b>Nathaniel Walser</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=nwalser" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/aaronhuggins"><img src="https://avatars.githubusercontent.com/u/16567111?v=4?s=100" width="100px;" alt="Aaron Huggins"/><br /><sub><b>Aaron Huggins</b></sub></a><br /><a href="#design-aaronhuggins" title="Design">🎨</a></td>
</tr>
</tbody> </tbody>
</table> </table>

View File

@@ -330,11 +330,6 @@ Obrigado vai para essas pessoas maravilhosas ([emoji key](https://allcontributor
<td align="center" valign="top" width="14.28%"><a href="https://github.com/wljince007"><img src="https://avatars.githubusercontent.com/u/88243938?v=4?s=100" width="100px;" alt="wljince007"/><br /><sub><b>wljince007</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=wljince007" title="Code">💻</a></td> <td align="center" valign="top" width="14.28%"><a href="https://github.com/wljince007"><img src="https://avatars.githubusercontent.com/u/88243938?v=4?s=100" width="100px;" alt="wljince007"/><br /><sub><b>wljince007</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=wljince007" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/FeroTheFox"><img src="https://avatars.githubusercontent.com/u/52982404?v=4?s=100" width="100px;" alt="fero"/><br /><sub><b>fero</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=FeroTheFox" title="Code">💻</a></td> <td align="center" valign="top" width="14.28%"><a href="https://github.com/FeroTheFox"><img src="https://avatars.githubusercontent.com/u/52982404?v=4?s=100" width="100px;" alt="fero"/><br /><sub><b>fero</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=FeroTheFox" title="Code">💻</a></td>
</tr> </tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://siebsie23.nl/"><img src="https://avatars.githubusercontent.com/u/25083973?v=4?s=100" width="100px;" alt="Sibren"/><br /><sub><b>Sibren</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=siebsie23" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://www.nathaniel-walser.com"><img src="https://avatars.githubusercontent.com/u/33339996?v=4?s=100" width="100px;" alt="Nathaniel Walser"/><br /><sub><b>Nathaniel Walser</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=nwalser" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/aaronhuggins"><img src="https://avatars.githubusercontent.com/u/16567111?v=4?s=100" width="100px;" alt="Aaron Huggins"/><br /><sub><b>Aaron Huggins</b></sub></a><br /><a href="#design-aaronhuggins" title="Design">🎨</a></td>
</tr>
</tbody> </tbody>
</table> </table>

View File

@@ -322,11 +322,6 @@ Pull-запросы и плагины приветствуются!
<td align="center" valign="top" width="14.28%"><a href="https://github.com/wljince007"><img src="https://avatars.githubusercontent.com/u/88243938?v=4?s=100" width="100px;" alt="wljince007"/><br /><sub><b>wljince007</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=wljince007" title="Code">💻</a></td> <td align="center" valign="top" width="14.28%"><a href="https://github.com/wljince007"><img src="https://avatars.githubusercontent.com/u/88243938?v=4?s=100" width="100px;" alt="wljince007"/><br /><sub><b>wljince007</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=wljince007" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/FeroTheFox"><img src="https://avatars.githubusercontent.com/u/52982404?v=4?s=100" width="100px;" alt="fero"/><br /><sub><b>fero</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=FeroTheFox" title="Code">💻</a></td> <td align="center" valign="top" width="14.28%"><a href="https://github.com/FeroTheFox"><img src="https://avatars.githubusercontent.com/u/52982404?v=4?s=100" width="100px;" alt="fero"/><br /><sub><b>fero</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=FeroTheFox" title="Code">💻</a></td>
</tr> </tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://siebsie23.nl/"><img src="https://avatars.githubusercontent.com/u/25083973?v=4?s=100" width="100px;" alt="Sibren"/><br /><sub><b>Sibren</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=siebsie23" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://www.nathaniel-walser.com"><img src="https://avatars.githubusercontent.com/u/33339996?v=4?s=100" width="100px;" alt="Nathaniel Walser"/><br /><sub><b>Nathaniel Walser</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=nwalser" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/aaronhuggins"><img src="https://avatars.githubusercontent.com/u/16567111?v=4?s=100" width="100px;" alt="Aaron Huggins"/><br /><sub><b>Aaron Huggins</b></sub></a><br /><a href="#design-aaronhuggins" title="Design">🎨</a></td>
</tr>
</tbody> </tbody>
</table> </table>

View File

@@ -321,11 +321,6 @@
<td align="center" valign="top" width="14.28%"><a href="https://github.com/wljince007"><img src="https://avatars.githubusercontent.com/u/88243938?v=4?s=100" width="100px;" alt="wljince007"/><br /><sub><b>wljince007</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=wljince007" title="Code">💻</a></td> <td align="center" valign="top" width="14.28%"><a href="https://github.com/wljince007"><img src="https://avatars.githubusercontent.com/u/88243938?v=4?s=100" width="100px;" alt="wljince007"/><br /><sub><b>wljince007</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=wljince007" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/FeroTheFox"><img src="https://avatars.githubusercontent.com/u/52982404?v=4?s=100" width="100px;" alt="fero"/><br /><sub><b>fero</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=FeroTheFox" title="Code">💻</a></td> <td align="center" valign="top" width="14.28%"><a href="https://github.com/FeroTheFox"><img src="https://avatars.githubusercontent.com/u/52982404?v=4?s=100" width="100px;" alt="fero"/><br /><sub><b>fero</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=FeroTheFox" title="Code">💻</a></td>
</tr> </tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://siebsie23.nl/"><img src="https://avatars.githubusercontent.com/u/25083973?v=4?s=100" width="100px;" alt="Sibren"/><br /><sub><b>Sibren</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=siebsie23" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://www.nathaniel-walser.com"><img src="https://avatars.githubusercontent.com/u/33339996?v=4?s=100" width="100px;" alt="Nathaniel Walser"/><br /><sub><b>Nathaniel Walser</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=nwalser" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/aaronhuggins"><img src="https://avatars.githubusercontent.com/u/16567111?v=4?s=100" width="100px;" alt="Aaron Huggins"/><br /><sub><b>Aaron Huggins</b></sub></a><br /><a href="#design-aaronhuggins" title="Design">🎨</a></td>
</tr>
</tbody> </tbody>
</table> </table>

View File

@@ -183,7 +183,7 @@ export class Application {
} }
enableTray (): void { enableTray (): void {
if (!!this.tray || process.platform === 'linux') { if (this.tray || process.platform === 'linux') {
return return
} }
if (process.platform === 'darwin') { if (process.platform === 'darwin') {

View File

@@ -1,14 +1,13 @@
import * as fs from 'fs' import * as fs from 'fs'
import * as path from 'path' import * as path from 'path'
import * as yaml from 'js-yaml' import * as yaml from 'js-yaml'
import { app } from 'electron'
import { writeFile } from 'atomically' import { writeFile } from 'atomically'
export const configPath = path.join(process.env.TABBY_CONFIG_DIRECTORY!, 'config.yaml')
const legacyConfigPath = path.join(process.env.TABBY_CONFIG_DIRECTORY!, '../terminus', 'config.yaml')
export function migrateConfig (): void { export function migrateConfig (): void {
const configPath = path.join(app.getPath('userData'), 'config.yaml')
const legacyConfigPath = path.join(app.getPath('userData'), '../terminus', 'config.yaml')
if (fs.existsSync(legacyConfigPath) && ( if (fs.existsSync(legacyConfigPath) && (
!fs.existsSync(configPath) || !fs.existsSync(configPath) ||
fs.statSync(configPath).mtime < fs.statSync(legacyConfigPath).mtime fs.statSync(configPath).mtime < fs.statSync(legacyConfigPath).mtime
@@ -20,6 +19,7 @@ export function migrateConfig (): void {
export function loadConfig (): any { export function loadConfig (): any {
migrateConfig() migrateConfig()
const configPath = path.join(app.getPath('userData'), 'config.yaml')
if (fs.existsSync(configPath)) { if (fs.existsSync(configPath)) {
return yaml.load(fs.readFileSync(configPath, 'utf8')) return yaml.load(fs.readFileSync(configPath, 'utf8'))
} else { } else {
@@ -27,6 +27,8 @@ export function loadConfig (): any {
} }
} }
const configPath = path.join(app.getPath('userData'), 'config.yaml')
export async function saveConfig (content: string): Promise<void> { export async function saveConfig (content: string): Promise<void> {
await writeFile(configPath, content, { encoding: 'utf8' }) await writeFile(configPath, content, { encoding: 'utf8' })
await writeFile(configPath + '.backup', content, { encoding: 'utf8' }) await writeFile(configPath + '.backup', content, { encoding: 'utf8' })

View File

@@ -1,21 +1,17 @@
import { app, ipcMain, Menu, dialog } from 'electron'
// set defaults of environment variables
import 'dotenv/config'
process.env.TABBY_PLUGINS ??= ''
process.env.TABBY_CONFIG_DIRECTORY ??= app.getPath('userData')
import 'v8-compile-cache' import 'v8-compile-cache'
import './portable' import './portable'
import 'source-map-support/register' import 'source-map-support/register'
import './sentry' import './sentry'
import './lru' import './lru'
import { app, ipcMain, Menu, dialog } from 'electron'
import { parseArgs } from './cli' import { parseArgs } from './cli'
import { Application } from './app' import { Application } from './app'
import electronDebug = require('electron-debug') import electronDebug = require('electron-debug')
import { loadConfig } from './config' import { loadConfig } from './config'
if (!process.env.TABBY_PLUGINS) {
process.env.TABBY_PLUGINS = ''
}
const argv = parseArgs(process.argv, process.cwd()) const argv = parseArgs(process.argv, process.cwd())

View File

@@ -26,7 +26,7 @@ abstract class GlasstronWindow extends BrowserWindow {
abstract setBlur (_: boolean) abstract setBlur (_: boolean)
} }
const macOSVibrancyType: any = process.platform === 'darwin' ? compareVersions(macOSRelease().version || '0.0', '10.14', '>=') ? 'under-window' : 'dark' : null const macOSVibrancyType = process.platform === 'darwin' ? compareVersions(macOSRelease().version || '0.0', '10.14', '>=') ? 'under-window' : 'dark' : null
const activityIcon = nativeImage.createFromPath(`${app.getAppPath()}/assets/activity.png`) const activityIcon = nativeImage.createFromPath(`${app.getAppPath()}/assets/activity.png`)

View File

@@ -31,7 +31,7 @@
"npm": "6", "npm": "6",
"rxjs": "^7.5.7", "rxjs": "^7.5.7",
"source-map-support": "^0.5.20", "source-map-support": "^0.5.20",
"v8-compile-cache": "^2.3.0", "v8-compile-cache": "^2.4.0",
"yargs": "^17.7.2" "yargs": "^17.7.2"
}, },
"optionalDependencies": { "optionalDependencies": {
@@ -64,7 +64,6 @@
}, },
"resolutions": { "resolutions": {
"*/node-abi": "^2.20.0", "*/node-abi": "^2.20.0",
"node-gyp": "10.0.0",
"nan": "github:jkleinsc/nan#remove_accessor_signature" "nan": "github:jkleinsc/nan#remove_accessor_signature"
} }
} }

View File

@@ -16,18 +16,6 @@
update-notifier "^2.2.0" update-notifier "^2.2.0"
yargs "^8.0.2" yargs "^8.0.2"
"@isaacs/cliui@^8.0.2":
version "8.0.2"
resolved "https://registry.yarnpkg.com/@isaacs/cliui/-/cliui-8.0.2.tgz#b37667b7bc181c168782259bab42474fbf52b550"
integrity sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==
dependencies:
string-width "^5.1.2"
string-width-cjs "npm:string-width@^4.2.0"
strip-ansi "^7.0.1"
strip-ansi-cjs "npm:strip-ansi@^6.0.1"
wrap-ansi "^8.1.0"
wrap-ansi-cjs "npm:wrap-ansi@^7.0.0"
"@ngx-translate/core@^14.0.0": "@ngx-translate/core@^14.0.0":
version "14.0.0" version "14.0.0"
resolved "https://registry.yarnpkg.com/@ngx-translate/core/-/core-14.0.0.tgz#af421d0e1a28376843f0fed375cd2fae7630a5ff" resolved "https://registry.yarnpkg.com/@ngx-translate/core/-/core-14.0.0.tgz#af421d0e1a28376843f0fed375cd2fae7630a5ff"
@@ -35,29 +23,6 @@
dependencies: dependencies:
tslib "^2.3.0" tslib "^2.3.0"
"@npmcli/agent@^2.0.0":
version "2.2.0"
resolved "https://registry.yarnpkg.com/@npmcli/agent/-/agent-2.2.0.tgz#e81f00fdb2a670750ff7731bbefb47ecbf0ccf44"
integrity sha512-2yThA1Es98orMkpSLVqlDZAMPK3jHJhifP2gnNUdk1754uZ8yI5c+ulCoVG+WlntQA6MzhrURMXjSd9Z7dJ2/Q==
dependencies:
agent-base "^7.1.0"
http-proxy-agent "^7.0.0"
https-proxy-agent "^7.0.1"
lru-cache "^10.0.1"
socks-proxy-agent "^8.0.1"
"@npmcli/fs@^3.1.0":
version "3.1.0"
resolved "https://registry.yarnpkg.com/@npmcli/fs/-/fs-3.1.0.tgz#233d43a25a91d68c3a863ba0da6a3f00924a173e"
integrity sha512-7kZUAaLscfgbwBQRbvdMYaZOWyMEcPTH/tJjnyAWJ/dvvs9Ef+CERx/qJb9GExJpl1qipaDGn7KqHnFGGixd0w==
dependencies:
semver "^7.3.5"
"@pkgjs/parseargs@^0.11.0":
version "0.11.0"
resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33"
integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==
"@serialport/binding-abstract@^9.0.2": "@serialport/binding-abstract@^9.0.2":
version "9.2.3" version "9.2.3"
resolved "https://registry.yarnpkg.com/@serialport/binding-abstract/-/binding-abstract-9.2.3.tgz#e7dd273357b6a698af7ad58db6f57f62443a0acb" resolved "https://registry.yarnpkg.com/@serialport/binding-abstract/-/binding-abstract-9.2.3.tgz#e7dd273357b6a698af7ad58db6f57f62443a0acb"
@@ -220,11 +185,6 @@ abbrev@1, abbrev@~1.1.1:
resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz" resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz"
integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==
abbrev@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-2.0.0.tgz#cf59829b8b4f03f89dda2771cb7f3653828c89bf"
integrity sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==
agent-base@4, agent-base@^4.3.0: agent-base@4, agent-base@^4.3.0:
version "4.3.0" version "4.3.0"
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.3.0.tgz#8165f01c436009bccad0b1d122f05ed770efc6ee" resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.3.0.tgz#8165f01c436009bccad0b1d122f05ed770efc6ee"
@@ -232,13 +192,6 @@ agent-base@4, agent-base@^4.3.0:
dependencies: dependencies:
es6-promisify "^5.0.0" es6-promisify "^5.0.0"
agent-base@^7.0.2, agent-base@^7.1.0:
version "7.1.0"
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-7.1.0.tgz#536802b76bc0b34aa50195eb2442276d613e3434"
integrity sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==
dependencies:
debug "^4.3.4"
agent-base@~4.2.1: agent-base@~4.2.1:
version "4.2.1" version "4.2.1"
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.2.1.tgz#d89e5999f797875674c07d87f260fc41e83e8ca9" resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.2.1.tgz#d89e5999f797875674c07d87f260fc41e83e8ca9"
@@ -253,14 +206,6 @@ agentkeepalive@^3.4.1:
dependencies: dependencies:
humanize-ms "^1.2.1" humanize-ms "^1.2.1"
aggregate-error@^3.0.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a"
integrity sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==
dependencies:
clean-stack "^2.0.0"
indent-string "^4.0.0"
ajv@^6.12.3: ajv@^6.12.3:
version "6.12.6" version "6.12.6"
resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz"
@@ -303,11 +248,6 @@ ansi-regex@^5.0.1:
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304"
integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==
ansi-regex@^6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.0.1.tgz#3183e38fae9a65d7cb5e53945cd5897d0260a06a"
integrity sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==
ansi-styles@^3.2.0, ansi-styles@^3.2.1: ansi-styles@^3.2.0, ansi-styles@^3.2.1:
version "3.2.1" version "3.2.1"
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d"
@@ -322,11 +262,6 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0:
dependencies: dependencies:
color-convert "^2.0.1" color-convert "^2.0.1"
ansi-styles@^6.1.0:
version "6.2.1"
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5"
integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==
ansicolors@~0.3.2: ansicolors@~0.3.2:
version "0.3.2" version "0.3.2"
resolved "https://registry.yarnpkg.com/ansicolors/-/ansicolors-0.3.2.tgz" resolved "https://registry.yarnpkg.com/ansicolors/-/ansicolors-0.3.2.tgz"
@@ -474,13 +409,6 @@ brace-expansion@^1.1.7:
balanced-match "^1.0.0" balanced-match "^1.0.0"
concat-map "0.0.1" concat-map "0.0.1"
brace-expansion@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae"
integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==
dependencies:
balanced-match "^1.0.0"
braces@^3.0.1: braces@^3.0.1:
version "3.0.2" version "3.0.2"
resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107"
@@ -545,24 +473,6 @@ cacache@^12.0.0, cacache@^12.0.2, cacache@^12.0.3:
unique-filename "^1.1.1" unique-filename "^1.1.1"
y18n "^4.0.0" y18n "^4.0.0"
cacache@^18.0.0:
version "18.0.0"
resolved "https://registry.yarnpkg.com/cacache/-/cacache-18.0.0.tgz#17a9ecd6e1be2564ebe6cdca5f7cfed2bfeb6ddc"
integrity sha512-I7mVOPl3PUCeRub1U8YoGz2Lqv9WOBpobZ8RyWFXmReuILz+3OAyTa5oH3QPdtKZD7N0Yk00aLfzn0qvp8dZ1w==
dependencies:
"@npmcli/fs" "^3.1.0"
fs-minipass "^3.0.0"
glob "^10.2.2"
lru-cache "^10.0.1"
minipass "^7.0.3"
minipass-collect "^1.0.2"
minipass-flush "^1.0.5"
minipass-pipeline "^1.2.4"
p-map "^4.0.0"
ssri "^10.0.0"
tar "^6.1.11"
unique-filename "^3.0.0"
call-bind@^1.0.0: call-bind@^1.0.0:
version "1.0.0" version "1.0.0"
resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.0.tgz#24127054bb3f9bdcb4b1fb82418186072f77b8ce" resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.0.tgz#24127054bb3f9bdcb4b1fb82418186072f77b8ce"
@@ -618,11 +528,6 @@ chownr@^1.1.1, chownr@^1.1.2, chownr@^1.1.4:
resolved "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz" resolved "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz"
integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==
chownr@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece"
integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==
ci-info@^1.5.0: ci-info@^1.5.0:
version "1.6.0" version "1.6.0"
resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.6.0.tgz#2ca20dbb9ceb32d4524a683303313f0304b1e497" resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.6.0.tgz#2ca20dbb9ceb32d4524a683303313f0304b1e497"
@@ -640,11 +545,6 @@ cidr-regex@^2.0.10:
dependencies: dependencies:
ip-regex "^2.1.0" ip-regex "^2.1.0"
clean-stack@^2.0.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b"
integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==
cli-boxes@^1.0.0: cli-boxes@^1.0.0:
version "1.0.0" version "1.0.0"
resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-1.0.0.tgz#4fa917c3e59c94a004cd61f8ee509da651687143" resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-1.0.0.tgz#4fa917c3e59c94a004cd61f8ee509da651687143"
@@ -852,15 +752,6 @@ cross-spawn@^6.0.5:
shebang-command "^1.2.0" shebang-command "^1.2.0"
which "^1.2.9" which "^1.2.9"
cross-spawn@^7.0.0:
version "7.0.3"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6"
integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==
dependencies:
path-key "^3.1.0"
shebang-command "^2.0.0"
which "^2.0.1"
crypto-random-string@^1.0.0: crypto-random-string@^1.0.0:
version "1.0.0" version "1.0.0"
resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-1.0.0.tgz#a230f64f568310e1498009940790ec99545bca7e" resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-1.0.0.tgz#a230f64f568310e1498009940790ec99545bca7e"
@@ -885,7 +776,7 @@ debug@3.1.0:
dependencies: dependencies:
ms "2.0.0" ms "2.0.0"
debug@4, debug@4.3.4, debug@^4.0.1, debug@^4.3.2, debug@^4.3.3, debug@^4.3.4: debug@4.3.4, debug@^4.0.1, debug@^4.3.2, debug@^4.3.3, debug@^4.3.4:
version "4.3.4" version "4.3.4"
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865"
integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==
@@ -1000,11 +891,6 @@ duplexify@^3.4.2, duplexify@^3.6.0:
readable-stream "^2.0.0" readable-stream "^2.0.0"
stream-shift "^1.0.0" stream-shift "^1.0.0"
eastasianwidth@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb"
integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==
ecc-jsbn@~0.1.1: ecc-jsbn@~0.1.1:
version "0.1.2" version "0.1.2"
resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz" resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz"
@@ -1088,12 +974,7 @@ emoji-regex@^8.0.0:
resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz"
integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==
emoji-regex@^9.2.2: encoding@^0.1.11:
version "9.2.2"
resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72"
integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==
encoding@^0.1.11, encoding@^0.1.13:
version "0.1.13" version "0.1.13"
resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.13.tgz#56574afdd791f54a8e9b2785c0582a2d26210fa9" resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.13.tgz#56574afdd791f54a8e9b2785c0582a2d26210fa9"
integrity sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A== integrity sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==
@@ -1122,11 +1003,6 @@ err-code@^1.0.0:
resolved "https://registry.yarnpkg.com/err-code/-/err-code-1.1.2.tgz" resolved "https://registry.yarnpkg.com/err-code/-/err-code-1.1.2.tgz"
integrity sha1-BuARbTAo9q70gGhJ6w6mp0iuaWA= integrity sha1-BuARbTAo9q70gGhJ6w6mp0iuaWA=
err-code@^2.0.2:
version "2.0.3"
resolved "https://registry.yarnpkg.com/err-code/-/err-code-2.0.3.tgz#23c2f3b756ffdfc608d30e27c9a941024807e7f9"
integrity sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==
errno@~0.1.7: errno@~0.1.7:
version "0.1.8" version "0.1.8"
resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.8.tgz#8bb3e9c7d463be4976ff888f76b4809ebc2e811f" resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.8.tgz#8bb3e9c7d463be4976ff888f76b4809ebc2e811f"
@@ -1208,11 +1084,6 @@ expand-template@^2.0.3:
resolved "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz" resolved "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz"
integrity sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg== integrity sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==
exponential-backoff@^3.1.1:
version "3.1.1"
resolved "https://registry.yarnpkg.com/exponential-backoff/-/exponential-backoff-3.1.1.tgz#64ac7526fe341ab18a39016cd22c787d01e00bf6"
integrity sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw==
extend@~3.0.2: extend@~3.0.2:
version "3.0.2" version "3.0.2"
resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz"
@@ -1291,14 +1162,6 @@ fontmanager-redux@1.1.0:
dependencies: dependencies:
node-addon-api "^3.0.2" node-addon-api "^3.0.2"
foreground-child@^3.1.0:
version "3.1.1"
resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.1.1.tgz#1d173e776d75d2772fed08efe4a0de1ea1b12d0d"
integrity sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==
dependencies:
cross-spawn "^7.0.0"
signal-exit "^4.0.1"
forever-agent@~0.6.1: forever-agent@~0.6.1:
version "0.6.1" version "0.6.1"
resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz" resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz"
@@ -1359,20 +1222,6 @@ fs-minipass@^1.2.7:
dependencies: dependencies:
minipass "^2.6.0" minipass "^2.6.0"
fs-minipass@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb"
integrity sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==
dependencies:
minipass "^3.0.0"
fs-minipass@^3.0.0:
version "3.0.3"
resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-3.0.3.tgz#79a85981c4dc120065e96f62086bf6f9dc26cc54"
integrity sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==
dependencies:
minipass "^7.0.3"
fs-vacuum@^1.2.10, fs-vacuum@~1.2.10: fs-vacuum@^1.2.10, fs-vacuum@~1.2.10:
version "1.2.10" version "1.2.10"
resolved "https://registry.yarnpkg.com/fs-vacuum/-/fs-vacuum-1.2.10.tgz#b7629bec07a4031a2548fdf99f5ecf1cc8b31e36" resolved "https://registry.yarnpkg.com/fs-vacuum/-/fs-vacuum-1.2.10.tgz#b7629bec07a4031a2548fdf99f5ecf1cc8b31e36"
@@ -1489,17 +1338,6 @@ glasstron@0.1.1:
node-addon-api "^4.0.0" node-addon-api "^4.0.0"
x11 "^2.3.0" x11 "^2.3.0"
glob@^10.2.2, glob@^10.3.10:
version "10.3.10"
resolved "https://registry.yarnpkg.com/glob/-/glob-10.3.10.tgz#0351ebb809fd187fe421ab96af83d3a70715df4b"
integrity sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==
dependencies:
foreground-child "^3.1.0"
jackspeak "^2.3.5"
minimatch "^9.0.1"
minipass "^5.0.0 || ^6.0.2 || ^7.0.0"
path-scurry "^1.10.1"
glob@^7.1.1, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: glob@^7.1.1, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6:
version "7.1.6" version "7.1.6"
resolved "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz" resolved "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz"
@@ -1536,7 +1374,7 @@ got@^6.7.1:
unzip-response "^2.0.1" unzip-response "^2.0.1"
url-parse-lax "^1.0.0" url-parse-lax "^1.0.0"
graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.2.4: graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.2.2, graceful-fs@^4.2.4:
version "4.2.4" version "4.2.4"
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz"
integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw== integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==
@@ -1546,11 +1384,6 @@ graceful-fs@^4.1.6, graceful-fs@^4.2.0:
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.8.tgz#e412b8d33f5e006593cbd3cee6df9f2cebbe802a" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.8.tgz#e412b8d33f5e006593cbd3cee6df9f2cebbe802a"
integrity sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg== integrity sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==
graceful-fs@^4.2.6:
version "4.2.11"
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3"
integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==
har-schema@^2.0.0: har-schema@^2.0.0:
version "2.0.0" version "2.0.0"
resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz" resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz"
@@ -1601,11 +1434,6 @@ http-cache-semantics@^3.8.1:
resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz#39b0e16add9b605bf0a9ef3d9daaf4843b4cacd2" resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz#39b0e16add9b605bf0a9ef3d9daaf4843b4cacd2"
integrity sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w== integrity sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w==
http-cache-semantics@^4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz#abe02fcb2985460bf0323be664436ec3476a6d5a"
integrity sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==
http-proxy-agent@^2.1.0: http-proxy-agent@^2.1.0:
version "2.1.0" version "2.1.0"
resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz#e4821beef5b2142a2026bd73926fe537631c5405" resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz#e4821beef5b2142a2026bd73926fe537631c5405"
@@ -1614,14 +1442,6 @@ http-proxy-agent@^2.1.0:
agent-base "4" agent-base "4"
debug "3.1.0" debug "3.1.0"
http-proxy-agent@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-7.0.0.tgz#e9096c5afd071a3fce56e6252bb321583c124673"
integrity sha512-+ZT+iBxVUQ1asugqnD6oWoRiS25AkjNfG085dKJGtGxkdwLQrMKU5wJr2bOOFAXzKcTuqq+7fZlTMgG3SRfIYQ==
dependencies:
agent-base "^7.1.0"
debug "^4.3.4"
http-signature@~1.2.0: http-signature@~1.2.0:
version "1.2.0" version "1.2.0"
resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz" resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz"
@@ -1639,14 +1459,6 @@ https-proxy-agent@^2.2.3:
agent-base "^4.3.0" agent-base "^4.3.0"
debug "^3.1.0" debug "^3.1.0"
https-proxy-agent@^7.0.1:
version "7.0.2"
resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-7.0.2.tgz#e2645b846b90e96c6e6f347fb5b2e41f1590b09b"
integrity sha512-NmLNjm6ucYwtcUmL7JQC1ZQ57LmHP4lT15FQ8D61nak1rO6DH+fz5qNK2Ap5UN4ZapYICE3/0KodcLYSPsPbaA==
dependencies:
agent-base "^7.0.2"
debug "4"
humanize-ms@^1.2.1: humanize-ms@^1.2.1:
version "1.2.1" version "1.2.1"
resolved "https://registry.yarnpkg.com/humanize-ms/-/humanize-ms-1.2.1.tgz" resolved "https://registry.yarnpkg.com/humanize-ms/-/humanize-ms-1.2.1.tgz"
@@ -1693,11 +1505,6 @@ imurmurhash@^0.1.4:
resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz" resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz"
integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= integrity sha1-khi5srkoojixPcT7a21XbyMUU+o=
indent-string@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251"
integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==
infer-owner@^1.0.3, infer-owner@^1.0.4: infer-owner@^1.0.3, infer-owner@^1.0.4:
version "1.0.4" version "1.0.4"
resolved "https://registry.yarnpkg.com/infer-owner/-/infer-owner-1.0.4.tgz" resolved "https://registry.yarnpkg.com/infer-owner/-/infer-owner-1.0.4.tgz"
@@ -1750,11 +1557,6 @@ ip@1.1.5:
resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a" resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a"
integrity sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo= integrity sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=
ip@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/ip/-/ip-2.0.0.tgz#4cf4ab182fee2314c75ede1276f8c80b479936da"
integrity sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==
is-arrayish@^0.2.1: is-arrayish@^0.2.1:
version "0.2.1" version "0.2.1"
resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d"
@@ -1833,11 +1635,6 @@ is-installed-globally@^0.1.0:
global-dirs "^0.1.0" global-dirs "^0.1.0"
is-path-inside "^1.0.0" is-path-inside "^1.0.0"
is-lambda@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/is-lambda/-/is-lambda-1.0.1.tgz#3d9877899e6a53efc0160504cde15f82e6f061d5"
integrity sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==
is-negative-zero@^2.0.0: is-negative-zero@^2.0.0:
version "2.0.1" version "2.0.1"
resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.1.tgz#3de746c18dda2319241a53675908d8f766f11c24" resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.1.tgz#3de746c18dda2319241a53675908d8f766f11c24"
@@ -1921,25 +1718,11 @@ isexe@^2.0.0:
resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz"
integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=
isexe@^3.1.1:
version "3.1.1"
resolved "https://registry.yarnpkg.com/isexe/-/isexe-3.1.1.tgz#4a407e2bd78ddfb14bea0c27c6f7072dde775f0d"
integrity sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==
isstream@~0.1.2: isstream@~0.1.2:
version "0.1.2" version "0.1.2"
resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz" resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz"
integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=
jackspeak@^2.3.5:
version "2.3.6"
resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-2.3.6.tgz#647ecc472238aee4b06ac0e461acc21a8c505ca8"
integrity sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==
dependencies:
"@isaacs/cliui" "^8.0.2"
optionalDependencies:
"@pkgjs/parseargs" "^0.11.0"
js-yaml@4.1.0, js-yaml@^4.1.0: js-yaml@4.1.0, js-yaml@^4.1.0:
version "4.1.0" version "4.1.0"
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602"
@@ -2286,11 +2069,6 @@ lowercase-keys@^1.0.0:
resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f"
integrity sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA== integrity sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==
lru-cache@^10.0.1, "lru-cache@^9.1.1 || ^10.0.0":
version "10.0.1"
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.0.1.tgz#0a3be479df549cca0e5d693ac402ff19537a6b7a"
integrity sha512-IJ4uwUTi2qCccrioU6g9g/5rvvVl13bsdczUUcqbciD9iLr095yj8DQKdObriEvuNSx325N1rV1O0sJFszx75g==
lru-cache@^4.0.1: lru-cache@^4.0.1:
version "4.1.5" version "4.1.5"
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd"
@@ -2327,23 +2105,6 @@ make-dir@^1.0.0:
dependencies: dependencies:
pify "^3.0.0" pify "^3.0.0"
make-fetch-happen@^13.0.0:
version "13.0.0"
resolved "https://registry.yarnpkg.com/make-fetch-happen/-/make-fetch-happen-13.0.0.tgz#705d6f6cbd7faecb8eac2432f551e49475bfedf0"
integrity sha512-7ThobcL8brtGo9CavByQrQi+23aIfgYU++wg4B87AIS8Rb2ZBt/MEaDqzA00Xwv/jUjAjYkLHjVolYuTLKda2A==
dependencies:
"@npmcli/agent" "^2.0.0"
cacache "^18.0.0"
http-cache-semantics "^4.1.1"
is-lambda "^1.0.1"
minipass "^7.0.2"
minipass-fetch "^3.0.0"
minipass-flush "^1.0.5"
minipass-pipeline "^1.2.4"
negotiator "^0.6.3"
promise-retry "^2.0.1"
ssri "^10.0.0"
make-fetch-happen@^5.0.0: make-fetch-happen@^5.0.0:
version "5.0.2" version "5.0.2"
resolved "https://registry.yarnpkg.com/make-fetch-happen/-/make-fetch-happen-5.0.2.tgz#aa8387104f2687edca01c8687ee45013d02d19bd" resolved "https://registry.yarnpkg.com/make-fetch-happen/-/make-fetch-happen-5.0.2.tgz#aa8387104f2687edca01c8687ee45013d02d19bd"
@@ -2410,57 +2171,11 @@ minimatch@^3.0.4:
dependencies: dependencies:
brace-expansion "^1.1.7" brace-expansion "^1.1.7"
minimatch@^9.0.1:
version "9.0.3"
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825"
integrity sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==
dependencies:
brace-expansion "^2.0.1"
minimist@^1.2.0, minimist@^1.2.3, minimist@^1.2.5, minimist@^1.2.6: minimist@^1.2.0, minimist@^1.2.3, minimist@^1.2.5, minimist@^1.2.6:
version "1.2.7" version "1.2.7"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.7.tgz#daa1c4d91f507390437c6a8bc01078e7000c4d18" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.7.tgz#daa1c4d91f507390437c6a8bc01078e7000c4d18"
integrity sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g== integrity sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==
minipass-collect@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/minipass-collect/-/minipass-collect-1.0.2.tgz#22b813bf745dc6edba2576b940022ad6edc8c617"
integrity sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==
dependencies:
minipass "^3.0.0"
minipass-fetch@^3.0.0:
version "3.0.4"
resolved "https://registry.yarnpkg.com/minipass-fetch/-/minipass-fetch-3.0.4.tgz#4d4d9b9f34053af6c6e597a64be8e66e42bf45b7"
integrity sha512-jHAqnA728uUpIaFm7NWsCnqKT6UqZz7GcI/bDpPATuwYyKwJwW0remxSCxUlKiEty+eopHGa3oc8WxgQ1FFJqg==
dependencies:
minipass "^7.0.3"
minipass-sized "^1.0.3"
minizlib "^2.1.2"
optionalDependencies:
encoding "^0.1.13"
minipass-flush@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/minipass-flush/-/minipass-flush-1.0.5.tgz#82e7135d7e89a50ffe64610a787953c4c4cbb373"
integrity sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==
dependencies:
minipass "^3.0.0"
minipass-pipeline@^1.2.4:
version "1.2.4"
resolved "https://registry.yarnpkg.com/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz#68472f79711c084657c067c5c6ad93cddea8214c"
integrity sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==
dependencies:
minipass "^3.0.0"
minipass-sized@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/minipass-sized/-/minipass-sized-1.0.3.tgz#70ee5a7c5052070afacfbc22977ea79def353b70"
integrity sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==
dependencies:
minipass "^3.0.0"
minipass@^2.3.5, minipass@^2.6.0, minipass@^2.9.0: minipass@^2.3.5, minipass@^2.6.0, minipass@^2.9.0:
version "2.9.0" version "2.9.0"
resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.9.0.tgz#e713762e7d3e32fed803115cf93e04bca9fcc9a6" resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.9.0.tgz#e713762e7d3e32fed803115cf93e04bca9fcc9a6"
@@ -2469,23 +2184,6 @@ minipass@^2.3.5, minipass@^2.6.0, minipass@^2.9.0:
safe-buffer "^5.1.2" safe-buffer "^5.1.2"
yallist "^3.0.0" yallist "^3.0.0"
minipass@^3.0.0:
version "3.3.6"
resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.3.6.tgz#7bba384db3a1520d18c9c0e5251c3444e95dd94a"
integrity sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==
dependencies:
yallist "^4.0.0"
minipass@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/minipass/-/minipass-5.0.0.tgz#3e9788ffb90b694a5d0ec94479a45b5d8738133d"
integrity sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==
"minipass@^5.0.0 || ^6.0.2 || ^7.0.0", minipass@^7.0.2, minipass@^7.0.3:
version "7.0.4"
resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.0.4.tgz#dbce03740f50a4786ba994c1fb908844d27b038c"
integrity sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==
minizlib@^1.3.3: minizlib@^1.3.3:
version "1.3.3" version "1.3.3"
resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.3.3.tgz#2290de96818a34c29551c8a8d301216bd65a861d" resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.3.3.tgz#2290de96818a34c29551c8a8d301216bd65a861d"
@@ -2493,14 +2191,6 @@ minizlib@^1.3.3:
dependencies: dependencies:
minipass "^2.9.0" minipass "^2.9.0"
minizlib@^2.1.1, minizlib@^2.1.2:
version "2.1.2"
resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931"
integrity sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==
dependencies:
minipass "^3.0.0"
yallist "^4.0.0"
mississippi@^3.0.0: mississippi@^3.0.0:
version "3.0.0" version "3.0.0"
resolved "https://registry.yarnpkg.com/mississippi/-/mississippi-3.0.0.tgz#ea0a3291f97e0b5e8776b363d5f0a12d94c67022" resolved "https://registry.yarnpkg.com/mississippi/-/mississippi-3.0.0.tgz#ea0a3291f97e0b5e8776b363d5f0a12d94c67022"
@@ -2529,11 +2219,6 @@ mkdirp@^0.5.1, mkdirp@^0.5.5, mkdirp@~0.5.0:
dependencies: dependencies:
minimist "^1.2.5" minimist "^1.2.5"
mkdirp@^1.0.3:
version "1.0.4"
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e"
integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==
move-concurrently@^1.0.1: move-concurrently@^1.0.1:
version "1.0.1" version "1.0.1"
resolved "https://registry.yarnpkg.com/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92" resolved "https://registry.yarnpkg.com/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92"
@@ -2591,11 +2276,6 @@ native-process-working-directory@^1.0.2:
dependencies: dependencies:
node-addon-api "^3.1.0" node-addon-api "^3.1.0"
negotiator@^0.6.3:
version "0.6.3"
resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd"
integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==
ngx-filesize@^3.0.2: ngx-filesize@^3.0.2:
version "3.0.2" version "3.0.2"
resolved "https://registry.yarnpkg.com/ngx-filesize/-/ngx-filesize-3.0.2.tgz#aab5ce9ce6eaa421f0393447d9c01653f3839a2c" resolved "https://registry.yarnpkg.com/ngx-filesize/-/ngx-filesize-3.0.2.tgz#aab5ce9ce6eaa421f0393447d9c01653f3839a2c"
@@ -2651,21 +2331,22 @@ node-gyp-build@4.6.0:
resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.6.0.tgz#0c52e4cbf54bbd28b709820ef7b6a3c2d6209055" resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.6.0.tgz#0c52e4cbf54bbd28b709820ef7b6a3c2d6209055"
integrity sha512-NTZVKn9IylLwUzaKjkas1e4u2DLNcV4rdYagA4PWdPwW87Bi7z+BznyKSRwS/761tV/lzCGXplWsiaMjLqP2zQ== integrity sha512-NTZVKn9IylLwUzaKjkas1e4u2DLNcV4rdYagA4PWdPwW87Bi7z+BznyKSRwS/761tV/lzCGXplWsiaMjLqP2zQ==
node-gyp@10.0.0, node-gyp@^5.0.2, node-gyp@^5.1.0: node-gyp@^5.0.2, node-gyp@^5.1.0:
version "10.0.0" version "5.1.1"
resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-10.0.0.tgz#b802e7177e79f8d7922db5a18b56983e88165f9e" resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-5.1.1.tgz#eb915f7b631c937d282e33aed44cb7a025f62a3e"
integrity sha512-LkaKUbjyacJGRHiuhUeUblzZNxTF1/XNooyAl6aiaJ6ZpeurR4Mk9sjxncGNSI7pETqyqM+hLAER0788oSxt0A== integrity sha512-WH0WKGi+a4i4DUt2mHnvocex/xPLp9pYt5R6M2JdFB7pJ7Z34hveZ4nDTGTiLXCkitA9T8HFZjhinBCiVHYcWw==
dependencies: dependencies:
env-paths "^2.2.0" env-paths "^2.2.0"
exponential-backoff "^3.1.1" glob "^7.1.4"
glob "^10.3.10" graceful-fs "^4.2.2"
graceful-fs "^4.2.6" mkdirp "^0.5.1"
make-fetch-happen "^13.0.0" nopt "^4.0.1"
nopt "^7.0.0" npmlog "^4.1.2"
proc-log "^3.0.0" request "^2.88.0"
semver "^7.3.5" rimraf "^2.6.3"
tar "^6.1.2" semver "^5.7.1"
which "^4.0.0" tar "^4.4.12"
which "^1.3.1"
node-pty@^1.0: node-pty@^1.0:
version "1.0.0" version "1.0.0"
@@ -2674,7 +2355,7 @@ node-pty@^1.0:
dependencies: dependencies:
nan "^2.17.0" nan "^2.17.0"
nopt@^4.0.3: nopt@^4.0.1, nopt@^4.0.3:
version "4.0.3" version "4.0.3"
resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.3.tgz#a375cad9d02fd921278d954c2254d5aa57e15e48" resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.3.tgz#a375cad9d02fd921278d954c2254d5aa57e15e48"
integrity sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg== integrity sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==
@@ -2682,13 +2363,6 @@ nopt@^4.0.3:
abbrev "1" abbrev "1"
osenv "^0.1.4" osenv "^0.1.4"
nopt@^7.0.0:
version "7.2.0"
resolved "https://registry.yarnpkg.com/nopt/-/nopt-7.2.0.tgz#067378c68116f602f552876194fd11f1292503d7"
integrity sha512-CVDtwCdhYIvnAzFoJ6NJ6dX3oga9/HyciQDnG1vQDjSLMeKLJ4A93ZqYKDrgYSr1FBY5/hMYC+2VCi24pgpkGA==
dependencies:
abbrev "^2.0.0"
normalize-package-data@^2.0.0, normalize-package-data@^2.3.2, normalize-package-data@^2.4.0, normalize-package-data@^2.5.0: normalize-package-data@^2.0.0, normalize-package-data@^2.3.2, normalize-package-data@^2.4.0, normalize-package-data@^2.5.0:
version "2.5.0" version "2.5.0"
resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8"
@@ -3077,13 +2751,6 @@ p-locate@^3.0.0:
dependencies: dependencies:
p-limit "^2.0.0" p-limit "^2.0.0"
p-map@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b"
integrity sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==
dependencies:
aggregate-error "^3.0.0"
p-try@^1.0.0: p-try@^1.0.0:
version "1.0.0" version "1.0.0"
resolved "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz" resolved "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz"
@@ -3196,24 +2863,11 @@ path-key@^2.0.0, path-key@^2.0.1:
resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40"
integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=
path-key@^3.1.0:
version "3.1.1"
resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375"
integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==
path-parse@^1.0.6: path-parse@^1.0.6:
version "1.0.7" version "1.0.7"
resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735"
integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==
path-scurry@^1.10.1:
version "1.10.1"
resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.10.1.tgz#9ba6bf5aa8500fe9fd67df4f0d9483b2b0bfc698"
integrity sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==
dependencies:
lru-cache "^9.1.1 || ^10.0.0"
minipass "^5.0.0 || ^6.0.2 || ^7.0.0"
path-type@^2.0.0: path-type@^2.0.0:
version "2.0.0" version "2.0.0"
resolved "https://registry.yarnpkg.com/path-type/-/path-type-2.0.0.tgz#f012ccb8415b7096fc2daa1054c3d72389594c73" resolved "https://registry.yarnpkg.com/path-type/-/path-type-2.0.0.tgz#f012ccb8415b7096fc2daa1054c3d72389594c73"
@@ -3272,11 +2926,6 @@ prepend-http@^1.0.1:
resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc"
integrity sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw= integrity sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=
proc-log@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/proc-log/-/proc-log-3.0.0.tgz#fb05ef83ccd64fd7b20bbe9c8c1070fc08338dd8"
integrity sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A==
process-nextick-args@~2.0.0: process-nextick-args@~2.0.0:
version "2.0.1" version "2.0.1"
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz"
@@ -3295,14 +2944,6 @@ promise-retry@^1.1.1:
err-code "^1.0.0" err-code "^1.0.0"
retry "^0.10.0" retry "^0.10.0"
promise-retry@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/promise-retry/-/promise-retry-2.0.1.tgz#ff747a13620ab57ba688f5fc67855410c370da22"
integrity sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==
dependencies:
err-code "^2.0.2"
retry "^0.12.0"
promzard@^0.3.0: promzard@^0.3.0:
version "0.3.0" version "0.3.0"
resolved "https://registry.yarnpkg.com/promzard/-/promzard-0.3.0.tgz" resolved "https://registry.yarnpkg.com/promzard/-/promzard-0.3.0.tgz"
@@ -3700,33 +3341,16 @@ shebang-command@^1.2.0:
dependencies: dependencies:
shebang-regex "^1.0.0" shebang-regex "^1.0.0"
shebang-command@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea"
integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==
dependencies:
shebang-regex "^3.0.0"
shebang-regex@^1.0.0: shebang-regex@^1.0.0:
version "1.0.0" version "1.0.0"
resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3"
integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=
shebang-regex@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172"
integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==
signal-exit@^3.0.0, signal-exit@^3.0.2: signal-exit@^3.0.0, signal-exit@^3.0.2:
version "3.0.3" version "3.0.3"
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz"
integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA== integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==
signal-exit@^4.0.1:
version "4.1.0"
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04"
integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==
simple-concat@^1.0.0: simple-concat@^1.0.0:
version "1.0.1" version "1.0.1"
resolved "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz" resolved "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz"
@@ -3756,11 +3380,6 @@ smart-buffer@^4.1.0:
resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.1.0.tgz" resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.1.0.tgz"
integrity sha512-iVICrxOzCynf/SNaBQCw34eM9jROU/s5rzIhpOvzhzuYHfJR/DhZfDkXiZSgKXfgv26HT3Yni3AV/DGw0cGnnw== integrity sha512-iVICrxOzCynf/SNaBQCw34eM9jROU/s5rzIhpOvzhzuYHfJR/DhZfDkXiZSgKXfgv26HT3Yni3AV/DGw0cGnnw==
smart-buffer@^4.2.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.2.0.tgz#6e1d71fa4f18c05f7d0ff216dd16a481d0e8d9ae"
integrity sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==
socks-proxy-agent@^4.0.0: socks-proxy-agent@^4.0.0:
version "4.0.2" version "4.0.2"
resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-4.0.2.tgz#3c8991f3145b2799e70e11bd5fbc8b1963116386" resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-4.0.2.tgz#3c8991f3145b2799e70e11bd5fbc8b1963116386"
@@ -3769,23 +3388,6 @@ socks-proxy-agent@^4.0.0:
agent-base "~4.2.1" agent-base "~4.2.1"
socks "~2.3.2" socks "~2.3.2"
socks-proxy-agent@^8.0.1:
version "8.0.2"
resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-8.0.2.tgz#5acbd7be7baf18c46a3f293a840109a430a640ad"
integrity sha512-8zuqoLv1aP/66PHF5TqwJ7Czm3Yv32urJQHrVyhD7mmA6d61Zv8cIXQYPTWwmg6qlupnPvs/QKDmfa4P/qct2g==
dependencies:
agent-base "^7.0.2"
debug "^4.3.4"
socks "^2.7.1"
socks@^2.7.1:
version "2.7.1"
resolved "https://registry.yarnpkg.com/socks/-/socks-2.7.1.tgz#d8e651247178fde79c0663043e07240196857d55"
integrity sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==
dependencies:
ip "^2.0.0"
smart-buffer "^4.2.0"
socks@~2.3.2: socks@~2.3.2:
version "2.3.3" version "2.3.3"
resolved "https://registry.yarnpkg.com/socks/-/socks-2.3.3.tgz#01129f0a5d534d2b897712ed8aceab7ee65d78e3" resolved "https://registry.yarnpkg.com/socks/-/socks-2.3.3.tgz#01129f0a5d534d2b897712ed8aceab7ee65d78e3"
@@ -3866,13 +3468,6 @@ sshpk@^1.7.0:
safer-buffer "^2.0.2" safer-buffer "^2.0.2"
tweetnacl "~0.14.0" tweetnacl "~0.14.0"
ssri@^10.0.0:
version "10.0.5"
resolved "https://registry.yarnpkg.com/ssri/-/ssri-10.0.5.tgz#e49efcd6e36385196cb515d3a2ad6c3f0265ef8c"
integrity sha512-bSf16tAFkGeRlUNDjXu8FzaMQt6g2HZJrun7mtMbIPOddxt3GLMSz5VWUWcqTJUPfLEaDIepGxv+bYQW49596A==
dependencies:
minipass "^7.0.3"
ssri@^6.0.0, ssri@^6.0.1: ssri@^6.0.0, ssri@^6.0.1:
version "6.0.2" version "6.0.2"
resolved "https://registry.yarnpkg.com/ssri/-/ssri-6.0.2.tgz#157939134f20464e7301ddba3e90ffa8f7728ac5" resolved "https://registry.yarnpkg.com/ssri/-/ssri-6.0.2.tgz#157939134f20464e7301ddba3e90ffa8f7728ac5"
@@ -3906,16 +3501,6 @@ strict-uri-encode@^2.0.0:
resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz#b9c7330c7042862f6b142dc274bbcc5866ce3546" resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz#b9c7330c7042862f6b142dc274bbcc5866ce3546"
integrity sha1-ucczDHBChi9rFC3CdLvMWGbONUY= integrity sha1-ucczDHBChi9rFC3CdLvMWGbONUY=
"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
name string-width-cjs
version "4.2.3"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
dependencies:
emoji-regex "^8.0.0"
is-fullwidth-code-point "^3.0.0"
strip-ansi "^6.0.1"
string-width@^1.0.1: string-width@^1.0.1:
version "1.0.2" version "1.0.2"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz" resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz"
@@ -3942,14 +3527,14 @@ string-width@^3.0.0, string-width@^3.1.0:
is-fullwidth-code-point "^2.0.0" is-fullwidth-code-point "^2.0.0"
strip-ansi "^5.1.0" strip-ansi "^5.1.0"
string-width@^5.0.1, string-width@^5.1.2: string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
version "5.1.2" version "4.2.3"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA== integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
dependencies: dependencies:
eastasianwidth "^0.2.0" emoji-regex "^8.0.0"
emoji-regex "^9.2.2" is-fullwidth-code-point "^3.0.0"
strip-ansi "^7.0.1" strip-ansi "^6.0.1"
string.prototype.trimend@^1.0.1: string.prototype.trimend@^1.0.1:
version "1.0.3" version "1.0.3"
@@ -3984,14 +3569,6 @@ stringify-package@^1.0.0, stringify-package@^1.0.1:
resolved "https://registry.yarnpkg.com/stringify-package/-/stringify-package-1.0.1.tgz#e5aa3643e7f74d0f28628b72f3dad5cecfc3ba85" resolved "https://registry.yarnpkg.com/stringify-package/-/stringify-package-1.0.1.tgz#e5aa3643e7f74d0f28628b72f3dad5cecfc3ba85"
integrity sha512-sa4DUQsYciMP1xhKWGuFM04fB0LG/9DlluZoSVywUMRNvzid6XucHK0/90xGxRoHrAaROrcHK1aPKaijCtSrhg== integrity sha512-sa4DUQsYciMP1xhKWGuFM04fB0LG/9DlluZoSVywUMRNvzid6XucHK0/90xGxRoHrAaROrcHK1aPKaijCtSrhg==
"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.1:
name strip-ansi-cjs
version "6.0.1"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
dependencies:
ansi-regex "^5.0.1"
strip-ansi@^3.0.0, strip-ansi@^3.0.1: strip-ansi@^3.0.0, strip-ansi@^3.0.1:
version "3.0.1" version "3.0.1"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz"
@@ -4020,12 +3597,12 @@ strip-ansi@^6.0.0:
dependencies: dependencies:
ansi-regex "^5.0.0" ansi-regex "^5.0.0"
strip-ansi@^7.0.1: strip-ansi@^6.0.1:
version "7.1.0" version "6.0.1"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
integrity sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ== integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
dependencies: dependencies:
ansi-regex "^6.0.1" ansi-regex "^5.0.1"
strip-bom@^3.0.0: strip-bom@^3.0.0:
version "3.0.0" version "3.0.0"
@@ -4082,7 +3659,7 @@ tar-stream@^2.1.4:
inherits "^2.0.3" inherits "^2.0.3"
readable-stream "^3.1.1" readable-stream "^3.1.1"
tar@^4.4.10, tar@^4.4.13: tar@^4.4.10, tar@^4.4.12, tar@^4.4.13:
version "4.4.19" version "4.4.19"
resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.19.tgz#2e4d7263df26f2b914dee10c825ab132123742f3" resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.19.tgz#2e4d7263df26f2b914dee10c825ab132123742f3"
integrity sha512-a20gEsvHnWe0ygBY8JbxoM4w3SJdhc7ZAuxkLqh+nvNQN2IOt0B5lLgM490X5Hl8FF0dl0tOf2ewFYAlIFgzVA== integrity sha512-a20gEsvHnWe0ygBY8JbxoM4w3SJdhc7ZAuxkLqh+nvNQN2IOt0B5lLgM490X5Hl8FF0dl0tOf2ewFYAlIFgzVA==
@@ -4095,18 +3672,6 @@ tar@^4.4.10, tar@^4.4.13:
safe-buffer "^5.2.1" safe-buffer "^5.2.1"
yallist "^3.1.1" yallist "^3.1.1"
tar@^6.1.11, tar@^6.1.2:
version "6.2.0"
resolved "https://registry.yarnpkg.com/tar/-/tar-6.2.0.tgz#b14ce49a79cb1cd23bc9b016302dea5474493f73"
integrity sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==
dependencies:
chownr "^2.0.0"
fs-minipass "^2.0.0"
minipass "^5.0.0"
minizlib "^2.1.1"
mkdirp "^1.0.3"
yallist "^4.0.0"
term-size@^1.2.0: term-size@^1.2.0:
version "1.2.0" version "1.2.0"
resolved "https://registry.yarnpkg.com/term-size/-/term-size-1.2.0.tgz#458b83887f288fc56d6fffbfad262e26638efa69" resolved "https://registry.yarnpkg.com/term-size/-/term-size-1.2.0.tgz#458b83887f288fc56d6fffbfad262e26638efa69"
@@ -4229,13 +3794,6 @@ unique-filename@^1.1.1:
dependencies: dependencies:
unique-slug "^2.0.0" unique-slug "^2.0.0"
unique-filename@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-3.0.0.tgz#48ba7a5a16849f5080d26c760c86cf5cf05770ea"
integrity sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==
dependencies:
unique-slug "^4.0.0"
unique-slug@^2.0.0: unique-slug@^2.0.0:
version "2.0.2" version "2.0.2"
resolved "https://registry.yarnpkg.com/unique-slug/-/unique-slug-2.0.2.tgz" resolved "https://registry.yarnpkg.com/unique-slug/-/unique-slug-2.0.2.tgz"
@@ -4243,13 +3801,6 @@ unique-slug@^2.0.0:
dependencies: dependencies:
imurmurhash "^0.1.4" imurmurhash "^0.1.4"
unique-slug@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/unique-slug/-/unique-slug-4.0.0.tgz#6bae6bb16be91351badd24cdce741f892a6532e3"
integrity sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==
dependencies:
imurmurhash "^0.1.4"
unique-string@^1.0.0: unique-string@^1.0.0:
version "1.0.0" version "1.0.0"
resolved "https://registry.yarnpkg.com/unique-string/-/unique-string-1.0.0.tgz#9e1057cca851abb93398f8b33ae187b99caec11a" resolved "https://registry.yarnpkg.com/unique-string/-/unique-string-1.0.0.tgz#9e1057cca851abb93398f8b33ae187b99caec11a"
@@ -4329,10 +3880,10 @@ uuid@^3.0.1, uuid@^3.3.2, uuid@^3.3.3:
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee"
integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==
v8-compile-cache@^2.3.0: v8-compile-cache@^2.4.0:
version "2.3.0" version "2.4.0"
resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee" resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.4.0.tgz#cdada8bec61e15865f05d097c5f4fd30e94dc128"
integrity sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA== integrity sha512-ocyWc3bAHBB/guyqJQVI5o4BZkPhznPYUG2ea80Gond/BgNWpap8TOmLSeeQG7bnh2KMISxskdADG59j7zruhw==
validate-npm-package-license@^3.0.1, validate-npm-package-license@^3.0.4: validate-npm-package-license@^3.0.1, validate-npm-package-license@^3.0.4:
version "3.0.4" version "3.0.4"
@@ -4382,20 +3933,6 @@ which@^1.2.9, which@^1.3.0, which@^1.3.1:
dependencies: dependencies:
isexe "^2.0.0" isexe "^2.0.0"
which@^2.0.1:
version "2.0.2"
resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1"
integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==
dependencies:
isexe "^2.0.0"
which@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/which/-/which-4.0.0.tgz#cd60b5e74503a3fbcfbf6cd6b4138a8bae644c1a"
integrity sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==
dependencies:
isexe "^3.1.1"
wide-align@^1.1.0: wide-align@^1.1.0:
version "1.1.3" version "1.1.3"
resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz" resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz"
@@ -4431,16 +3968,6 @@ worker-farm@^1.6.0, worker-farm@^1.7.0:
dependencies: dependencies:
errno "~0.1.7" errno "~0.1.7"
"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0:
name wrap-ansi-cjs
version "7.0.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
dependencies:
ansi-styles "^4.0.0"
string-width "^4.1.0"
strip-ansi "^6.0.0"
wrap-ansi@^2.0.0: wrap-ansi@^2.0.0:
version "2.1.0" version "2.1.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85"
@@ -4458,14 +3985,14 @@ wrap-ansi@^5.1.0:
string-width "^3.0.0" string-width "^3.0.0"
strip-ansi "^5.0.0" strip-ansi "^5.0.0"
wrap-ansi@^8.1.0: wrap-ansi@^7.0.0:
version "8.1.0" version "7.0.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
integrity sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ== integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
dependencies: dependencies:
ansi-styles "^6.1.0" ansi-styles "^4.0.0"
string-width "^5.0.1" string-width "^4.1.0"
strip-ansi "^7.0.1" strip-ansi "^6.0.0"
wrappy@1: wrappy@1:
version "1.0.2" version "1.0.2"

View File

@@ -2,6 +2,7 @@
appId: org.tabby appId: org.tabby
productName: Tabby productName: Tabby
compression: normal compression: normal
npmRebuild: false
files: files:
- '**/*' - '**/*'
- dist - dist

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -26,8 +26,8 @@
"@types/js-yaml": "^4.0.5", "@types/js-yaml": "^4.0.5",
"@types/node": "20.3.1", "@types/node": "20.3.1",
"@types/webpack-env": "^1.18.0", "@types/webpack-env": "^1.18.0",
"@typescript-eslint/eslint-plugin": "^6.4.1", "@typescript-eslint/eslint-plugin": "^5.45.0",
"@typescript-eslint/parser": "^6.4.1", "@typescript-eslint/parser": "^5.54.1",
"apply-loader": "2.0.0", "apply-loader": "2.0.0",
"axios": "^1.4.0", "axios": "^1.4.0",
"babel-loader": "^9.1.2", "babel-loader": "^9.1.2",
@@ -40,13 +40,13 @@
"css-loader": "^6.7.3", "css-loader": "^6.7.3",
"deep-equal": "2.0.5", "deep-equal": "2.0.5",
"electron": "^25.3.0", "electron": "^25.3.0",
"electron-builder": "^24.6.4", "electron-builder": "^24.0.0-alpha.1",
"electron-download": "^4.1.1", "electron-download": "^4.1.1",
"electron-installer-snap": "^5.1.0", "electron-installer-snap": "^5.1.0",
"electron-rebuild": "^3.2.9", "electron-rebuild": "^3.2.9",
"eslint": "^8.48.0", "eslint": "^8.38.0",
"eslint-import-resolver-typescript": "^3.6.0", "eslint-import-resolver-typescript": "^3.5.2",
"eslint-plugin-import": "^2.28.1", "eslint-plugin-import": "^2.27.5",
"file-loader": "^6.2.0", "file-loader": "^6.2.0",
"gettext-extractor": "^3.8.0", "gettext-extractor": "^3.8.0",
"graceful-fs": "^4.2.10", "graceful-fs": "^4.2.10",
@@ -96,10 +96,9 @@
"resolutions": { "resolutions": {
"*/pug": "^3", "*/pug": "^3",
"lzma-native": "^8.0.6", "lzma-native": "^8.0.6",
"*/node-abi": "^3.51.0", "*/node-abi": "^3.33.0",
"**/graceful-fs": "^4.2.4", "**/graceful-fs": "^4.2.4",
"nan": "2.17.0", "nan": "2.17.0"
"node-gyp": "10.0.0"
}, },
"scripts": { "scripts": {
"build": "npm run build:typings && node scripts/build-modules.mjs", "build": "npm run build:typings && node scripts/build-modules.mjs",
@@ -116,8 +115,5 @@
"i18n:push": "crowdin push" "i18n:push": "crowdin push"
}, },
"type": "module", "type": "module",
"private": true, "private": true
"dependencies": {
"dotenv": "^16.3.1"
}
} }

View File

@@ -1,45 +0,0 @@
diff --git a/node_modules/electron-rebuild/lib/src/module-rebuilder.js b/node_modules/electron-rebuild/lib/src/module-rebuilder.js
index 0d78dbe..60ee50d 100644
--- a/node_modules/electron-rebuild/lib/src/module-rebuilder.js
+++ b/node_modules/electron-rebuild/lib/src/module-rebuilder.js
@@ -123,7 +123,7 @@ class ModuleRebuilder {
await fs.outputFile(this.metaPath, this.metaData);
}
async rebuild(cacheKey) {
- return (await this.findPrebuildifyModule(cacheKey)) ||
+ return
(await this.findPrebuildInstallModule(cacheKey)) ||
(await this.rebuildNodeGypModule(cacheKey));
}
diff --git a/node_modules/electron-rebuild/lib/src/module-walker.js b/node_modules/electron-rebuild/lib/src/module-walker.js
index b36e35c..09c6d03 100644
--- a/node_modules/electron-rebuild/lib/src/module-walker.js
+++ b/node_modules/electron-rebuild/lib/src/module-walker.js
@@ -57,6 +57,7 @@ class ModuleWalker {
return;
}
d('exploring', modulePath);
+
let childPackageJson;
try {
childPackageJson = await (0, read_package_json_1.readPackageJson)(modulePath, true);
diff --git a/node_modules/electron-rebuild/lib/src/rebuild.js b/node_modules/electron-rebuild/lib/src/rebuild.js
index 41e3a3e..3f63287 100644
--- a/node_modules/electron-rebuild/lib/src/rebuild.js
+++ b/node_modules/electron-rebuild/lib/src/rebuild.js
@@ -101,6 +101,7 @@ class Rebuilder {
await this.moduleWalker.findAllModulesIn(nodeModulesPath);
}
for (const modulePath of this.moduleWalker.modulesToRebuild) {
+ await this.rebuildModuleAt(modulePath)
this.rebuilds.push(() => this.rebuildModuleAt(modulePath));
}
this.rebuilds.push(() => this.rebuildModuleAt(this.buildPath));
@@ -117,6 +118,7 @@ class Rebuilder {
if (!(await fs.pathExists(path.resolve(modulePath, 'binding.gyp')))) {
return;
}
+
const moduleRebuilder = new module_rebuilder_1.ModuleRebuilder(this, modulePath);
this.lifecycle.emit('module-found', path.basename(modulePath));
if (!this.force && await moduleRebuilder.alreadyBuiltByRebuild()) {

View File

@@ -18,7 +18,7 @@ process.env.APPLE_APP_SPECIFIC_PASSWORD ??= process.env.APPSTORE_PASSWORD
builder({ builder({
dir: true, dir: true,
mac: ['dmg', 'zip'], mac: ['pkg', 'zip'],
x64: process.env.ARCH === 'x86_64', x64: process.env.ARCH === 'x86_64',
arm64: process.env.ARCH === 'arm64', arm64: process.env.ARCH === 'arm64',
config: { config: {
@@ -32,6 +32,7 @@ builder({
teamId: process.env.APPLE_TEAM_ID, teamId: process.env.APPLE_TEAM_ID,
} : false, } : false,
}, },
npmRebuild: process.env.ARCH !== 'arm64',
publish: process.env.KEYGEN_TOKEN ? [ publish: process.env.KEYGEN_TOKEN ? [
vars.keygenConfig, vars.keygenConfig,
{ {

View File

@@ -16,7 +16,7 @@ export { BootstrapData, PluginInfo, BOOTSTRAP_DATA } from './mainProcess'
export { HostWindowService } from './hostWindow' export { HostWindowService } from './hostWindow'
export { HostAppService, Platform } from './hostApp' export { HostAppService, Platform } from './hostApp'
export { FileProvider } from './fileProvider' export { FileProvider } from './fileProvider'
export { ProfileProvider, ConnectableProfileProvider, QuickConnectProfileProvider, Profile, ConnectableProfile, PartialProfile, ProfileSettingsComponent, ProfileGroup, PartialProfileGroup } from './profileProvider' export { ProfileProvider, Profile, PartialProfile, ProfileSettingsComponent } from './profileProvider'
export { PromptModalComponent } from '../components/promptModal.component' export { PromptModalComponent } from '../components/promptModal.component'
export * from './commands' export * from './commands'

View File

@@ -1,5 +1,5 @@
export interface MenuItemOptions { export interface MenuItemOptions {
type?: 'normal' | 'separator' | 'submenu' | 'checkbox' | 'radio' type?: ('normal' | 'separator' | 'submenu' | 'checkbox' | 'radio')
label?: string label?: string
sublabel?: string sublabel?: string
enabled?: boolean enabled?: boolean

View File

@@ -21,10 +21,6 @@ export interface Profile {
isTemplate: boolean isTemplate: boolean
} }
export interface ConnectableProfile extends Profile {
clearServiceMessagesOnConnect: boolean
}
export type PartialProfile<T extends Profile> = Omit<Omit<Omit<{ export type PartialProfile<T extends Profile> = Omit<Omit<Omit<{
[K in keyof T]?: T[K] [K in keyof T]?: T[K]
}, 'options'>, 'type'>, 'name'> & { }, 'options'>, 'type'>, 'name'> & {
@@ -35,21 +31,6 @@ export type PartialProfile<T extends Profile> = Omit<Omit<Omit<{
} }
} }
export interface ProfileGroup {
id: string
name: string
profiles: PartialProfile<Profile>[]
defaults: any
editable: boolean
}
export type PartialProfileGroup<T extends ProfileGroup> = Omit<Omit<{
[K in keyof T]?: T[K]
}, 'id'>, 'name'> & {
id: string
name: string
}
export interface ProfileSettingsComponent<P extends Profile> { export interface ProfileSettingsComponent<P extends Profile> {
profile: P profile: P
save?: () => void save?: () => void
@@ -58,6 +39,7 @@ export interface ProfileSettingsComponent<P extends Profile> {
export abstract class ProfileProvider<P extends Profile> { export abstract class ProfileProvider<P extends Profile> {
id: string id: string
name: string name: string
supportsQuickConnect = false
settingsComponent?: new (...args: any[]) => ProfileSettingsComponent<P> settingsComponent?: new (...args: any[]) => ProfileSettingsComponent<P>
configDefaults = {} configDefaults = {}
@@ -71,15 +53,13 @@ export abstract class ProfileProvider<P extends Profile> {
abstract getDescription (profile: PartialProfile<P>): string abstract getDescription (profile: PartialProfile<P>): string
quickConnect (query: string): PartialProfile<P>|null {
return null
}
intoQuickConnectString (profile: P): string|null {
return null
}
deleteProfile (profile: P): void { } deleteProfile (profile: P): void { }
} }
export abstract class ConnectableProfileProvider<P extends ConnectableProfile> extends ProfileProvider<P> {}
export abstract class QuickConnectProfileProvider<P extends ConnectableProfile> extends ConnectableProfileProvider<P> {
abstract quickConnect (query: string): PartialProfile<P>|null
abstract intoQuickConnectString (profile: P): string|null
}

View File

@@ -18,7 +18,7 @@ export class CoreCommandProvider extends CommandProvider {
} }
async activate () { async activate () {
const profile = await this.profilesService.showProfileSelector().catch(() => null) const profile = await this.profilesService.showProfileSelector()
if (profile) { if (profile) {
this.profilesService.launchProfile(profile) this.profilesService.launchProfile(profile)
} }

View File

@@ -35,7 +35,8 @@ title-bar(
[@animateTab]='{value: "in", params: {size: targetTabSize}}', [@animateTab]='{value: "in", params: {size: targetTabSize}}',
[@.disabled]='hasVerticalTabs() || !config.store.accessibility.animations', [@.disabled]='hasVerticalTabs() || !config.store.accessibility.animations',
(click)='app.selectTab(tab)', (click)='app.selectTab(tab)',
[class.fully-draggable]='hostApp.platform != Platform.macOS' [class.fully-draggable]='hostApp.platform != Platform.macOS',
[class.drag-region]='hostApp.platform == Platform.macOS && !(app.tabDragActive$|async)',
) )
.btn-group.background .btn-group.background
@@ -64,7 +65,7 @@ title-bar(
(transfersChange)='onTransfersChange()' (transfersChange)='onTransfersChange()'
) )
.drag-space.background([class.persistent]='config.store.appearance.frame == "thin"') .drag-space.background([class.persistent]='config.store.appearance.frame == "thin" && hostApp.platform != Platform.macOS')
.btn-group.background .btn-group.background
.d-flex( .d-flex(

View File

@@ -75,7 +75,6 @@ export abstract class BaseTabComponent extends BaseComponent {
private titleChange = new Subject<string>() private titleChange = new Subject<string>()
private focused = new Subject<void>() private focused = new Subject<void>()
private blurred = new Subject<void>() private blurred = new Subject<void>()
private visibility = new Subject<boolean>()
private progress = new Subject<number|null>() private progress = new Subject<number|null>()
private activity = new Subject<boolean>() private activity = new Subject<boolean>()
private destroyed = new Subject<void>() private destroyed = new Subject<void>()
@@ -84,8 +83,6 @@ export abstract class BaseTabComponent extends BaseComponent {
get focused$ (): Observable<void> { return this.focused } get focused$ (): Observable<void> { return this.focused }
get blurred$ (): Observable<void> { return this.blurred } get blurred$ (): Observable<void> { return this.blurred }
/* @hidden */
get visibility$ (): Observable<boolean> { return this.visibility }
get titleChange$ (): Observable<string> { return this.titleChange.pipe(distinctUntilChanged()) } get titleChange$ (): Observable<string> { return this.titleChange.pipe(distinctUntilChanged()) }
get progress$ (): Observable<number|null> { return this.progress.pipe(distinctUntilChanged()) } get progress$ (): Observable<number|null> { return this.progress.pipe(distinctUntilChanged()) }
get activity$ (): Observable<boolean> { return this.activity } get activity$ (): Observable<boolean> { return this.activity }
@@ -180,11 +177,6 @@ export abstract class BaseTabComponent extends BaseComponent {
this.blurred.next() this.blurred.next()
} }
/* @hidden */
emitVisibility (visibility: boolean): void {
this.visibility.next(visibility)
}
insertIntoContainer (container: ViewContainerRef): EmbeddedViewRef<any> { insertIntoContainer (container: ViewContainerRef): EmbeddedViewRef<any> {
this.viewContainerEmbeddedRef = container.insert(this.hostView) as EmbeddedViewRef<any> this.viewContainerEmbeddedRef = container.insert(this.hostView) as EmbeddedViewRef<any>
this.viewContainer = container this.viewContainer = container

View File

@@ -18,26 +18,22 @@ export class SelectorModalComponent<T> {
@Input() selectedIndex = 0 @Input() selectedIndex = 0
hasGroups = false hasGroups = false
@ViewChildren('item') itemChildren: QueryList<ElementRef> @ViewChildren('item') itemChildren: QueryList<ElementRef>
private preventEdit: boolean
constructor (public modalInstance: NgbActiveModal) { constructor (
this.preventEdit = false public modalInstance: NgbActiveModal,
} ) { }
ngOnInit (): void { ngOnInit (): void {
this.onFilterChange() this.onFilterChange()
this.hasGroups = this.options.some(x => x.group) this.hasGroups = this.options.some(x => x.group)
} }
@HostListener('keydown', ['$event']) onKeyDown (event: KeyboardEvent): void { @HostListener('keydown', ['$event']) onKeyUp (event: KeyboardEvent): void {
if (event.key === 'Escape') {
this.close()
} else if (this.filteredOptions.length > 0) {
if (event.key === 'PageUp' || event.key === 'ArrowUp' && event.metaKey) { if (event.key === 'PageUp' || event.key === 'ArrowUp' && event.metaKey) {
this.selectedIndex -= Math.min(10, Math.max(1, this.selectedIndex)) this.selectedIndex -= 10
event.preventDefault() event.preventDefault()
} else if (event.key === 'PageDown' || event.key === 'ArrowDown' && event.metaKey) { } else if (event.key === 'PageDown' || event.key === 'ArrowDown' && event.metaKey) {
this.selectedIndex += Math.min(10, Math.max(1, this.filteredOptions.length - this.selectedIndex - 1)) this.selectedIndex += 10
event.preventDefault() event.preventDefault()
} else if (event.key === 'ArrowUp') { } else if (event.key === 'ArrowUp') {
this.selectedIndex-- this.selectedIndex--
@@ -47,30 +43,21 @@ export class SelectorModalComponent<T> {
event.preventDefault() event.preventDefault()
} else if (event.key === 'Enter') { } else if (event.key === 'Enter') {
this.selectOption(this.filteredOptions[this.selectedIndex]) this.selectOption(this.filteredOptions[this.selectedIndex])
} else if (event.key === 'Backspace' && !this.preventEdit) { } else if (event.key === 'Escape') {
if (this.canEditSelected()) { this.close()
}
if (event.key === 'Backspace' && this.canEditSelected()) {
event.preventDefault() event.preventDefault()
this.filter = this.filteredOptions[this.selectedIndex].freeInputEquivalent! this.filter = this.filteredOptions[this.selectedIndex].freeInputEquivalent!
this.onFilterChange() this.onFilterChange()
} else {
this.preventEdit = true
}
} }
this.selectedIndex = (this.selectedIndex + this.filteredOptions.length) % this.filteredOptions.length this.selectedIndex = (this.selectedIndex + this.filteredOptions.length) % this.filteredOptions.length
Array.from(this.itemChildren)[this.selectedIndex]?.nativeElement.scrollIntoView({ Array.from(this.itemChildren)[this.selectedIndex]?.nativeElement.scrollIntoView({
behavior: 'smooth', behavior: 'smooth',
block: 'nearest', block: 'nearest',
}) })
} }
}
@HostListener('keyup', ['$event']) onKeyUp (event: KeyboardEvent): void {
if (event.key === 'Backspace' && this.preventEdit) {
this.preventEdit = false
}
}
onFilterChange (): void { onFilterChange (): void {
const f = this.filter.trim().toLowerCase() const f = this.filter.trim().toLowerCase()
@@ -89,7 +76,7 @@ export class SelectorModalComponent<T> {
{ sort: true }, { sort: true },
).search(f) ).search(f)
this.options.filter(x => x.freeInputPattern).sort(firstBy<SelectorOption<T>, number>(x => x.weight ?? 0)).forEach(freeOption => { this.options.filter(x => x.freeInputPattern).forEach(freeOption => {
if (!this.filteredOptions.includes(freeOption)) { if (!this.filteredOptions.includes(freeOption)) {
this.filteredOptions.push(freeOption) this.filteredOptions.push(freeOption)
} }

View File

@@ -275,7 +275,6 @@ export class SplitTabComponent extends BaseTabComponent implements AfterViewInit
} }
}) })
this.blurred$.subscribe(() => this.getAllTabs().forEach(x => x.emitBlurred())) this.blurred$.subscribe(() => this.getAllTabs().forEach(x => x.emitBlurred()))
this.visibility$.subscribe(visibility => this.getAllTabs().forEach(x => x.emitVisibility(visibility)))
this.tabAdded$.subscribe(() => this.updateTitle()) this.tabAdded$.subscribe(() => this.updateTitle())
this.tabRemoved$.subscribe(() => this.updateTitle()) this.tabRemoved$.subscribe(() => this.updateTitle())

View File

@@ -1,10 +1,10 @@
.container.mt-3.mb-3 .container.mt-5.mb-5
.mb-3 .mb-4
.tabby-logo .tabby-logo
h1.tabby-title Tabby h1.tabby-title Tabby
sup α sup α
.text-center.mb-3(translate) Thank you for downloading Tabby! .text-center.mb-5(translate) Thank you for downloading Tabby!
.form-line .form-line
.header .header
@@ -16,54 +16,13 @@
*ngFor='let lang of allLanguages' *ngFor='let lang of allLanguages'
) {{lang.name}} ) {{lang.name}}
.form-line
.header
.title(translate) Switch color scheme
.btn-group(role='group')
input.btn-check(
type='radio',
name='colorSchemeMode',
[(ngModel)]='config.store.appearance.colorSchemeMode',
(ngModelChange)='config.save()',
id='colorSchemeModeAuto',
[value]='"auto"'
)
label.btn.btn-secondary(
for='colorSchemeModeAuto'
)
span(translate) From system
input.btn-check(
type='radio',
name='colorSchemeMode',
[(ngModel)]='config.store.appearance.colorSchemeMode',
(ngModelChange)='config.save()',
id='colorSchemeModeDark',
[value]='"dark"'
)
label.btn.btn-secondary(
for='colorSchemeModeDark'
)
span(translate) Always dark
input.btn-check(
type='radio',
name='colorSchemeMode',
[(ngModel)]='config.store.appearance.colorSchemeMode',
(ngModelChange)='config.save()',
id='colorSchemeModeLight',
[value]='"light"'
)
label.btn.btn-secondary(
for='colorSchemeModeLight'
)
span(translate) Always light
.form-line .form-line
.header .header
.title(translate) Enable analytics .title(translate) Enable analytics
.description(translate) Help track the number of Tabby installs across the world! .description(translate) Help track the number of Tabby installs across the world!
toggle([(ngModel)]='config.store.enableAnalytics') toggle([(ngModel)]='config.store.enableAnalytics')
.form-line .form-line
.header .header
.title(translate) Enable global hotkey (Ctrl-Space) .title(translate) Enable global hotkey (Ctrl-Space)

View File

@@ -6,8 +6,3 @@
max-height: 100%; max-height: 100%;
overflow-y: auto; overflow-y: auto;
} }
.tabby-logo {
width: 60px;
height: 60px;
}

View File

@@ -9,6 +9,5 @@ export class CoreConfigProvider extends ConfigProvider {
[Platform.Linux]: require('./configDefaults.linux.yaml').default, [Platform.Linux]: require('./configDefaults.linux.yaml').default,
[Platform.Web]: require('./configDefaults.web.yaml').default, [Platform.Web]: require('./configDefaults.web.yaml').default,
} }
defaults = require('./configDefaults.yaml').default defaults = require('./configDefaults.yaml').default
} }

View File

@@ -96,3 +96,5 @@ hotkeys:
- '⌘-Shift-E' - '⌘-Shift-E'
command-selector: command-selector:
- '⌘-Shift-P' - '⌘-Shift-P'
appearance:
vibrancy: true

View File

@@ -19,7 +19,6 @@ appearance:
vibrancyType: 'blur' vibrancyType: 'blur'
lastTabClosesWindow: false lastTabClosesWindow: false
spaciness: 1 spaciness: 1
colorSchemeMode: 'dark'
terminal: terminal:
showBuiltinProfiles: true showBuiltinProfiles: true
showRecentProfiles: 3 showRecentProfiles: 3
@@ -32,7 +31,6 @@ hotkeys:
profile-selectors: profile-selectors:
__nonStructural: true __nonStructural: true
profiles: [] profiles: []
groups: []
profileDefaults: profileDefaults:
__nonStructural: true __nonStructural: true
ssh: ssh:

View File

@@ -2,6 +2,7 @@ import { Injectable } from '@angular/core'
import { TranslateService } from '@ngx-translate/core' import { TranslateService } from '@ngx-translate/core'
import { ProfilesService } from './services/profiles.service' import { ProfilesService } from './services/profiles.service'
import { HotkeyDescription, HotkeyProvider } from './api/hotkeyProvider' import { HotkeyDescription, HotkeyProvider } from './api/hotkeyProvider'
import { PartialProfile, Profile } from './api'
/** @hidden */ /** @hidden */
@Injectable() @Injectable()
@@ -267,7 +268,7 @@ export class AppHotkeyProvider extends HotkeyProvider {
return [ return [
...this.hotkeys, ...this.hotkeys,
...profiles.map(profile => ({ ...profiles.map(profile => ({
id: `profile.${ProfilesService.getProfileHotkeyName(profile)}`, id: `profile.${AppHotkeyProvider.getProfileHotkeyName(profile)}`,
name: this.translate.instant('New tab: {profile}', { profile: profile.name }), name: this.translate.instant('New tab: {profile}', { profile: profile.name }),
})), })),
...this.profilesService.getProviders().map(provider => ({ ...this.profilesService.getProviders().map(provider => ({
@@ -277,4 +278,7 @@ export class AppHotkeyProvider extends HotkeyProvider {
] ]
} }
static getProfileHotkeyName (profile: PartialProfile<Profile>): string {
return (profile.id ?? profile.name).replace(/\./g, '-')
}
} }

View File

@@ -37,7 +37,7 @@ import { FastHtmlBindDirective } from './directives/fastHtmlBind.directive'
import { DropZoneDirective } from './directives/dropZone.directive' import { DropZoneDirective } from './directives/dropZone.directive'
import { CdkAutoDropGroup } from './directives/cdkAutoDropGroup.directive' import { CdkAutoDropGroup } from './directives/cdkAutoDropGroup.directive'
import { Theme, CLIHandler, TabContextMenuItemProvider, TabRecoveryProvider, HotkeyProvider, ConfigProvider, PlatformService, FileProvider, ProfilesService, ProfileProvider, QuickConnectProfileProvider, SelectorOption, Profile, SelectorService, CommandProvider } from './api' import { Theme, CLIHandler, TabContextMenuItemProvider, TabRecoveryProvider, HotkeyProvider, ConfigProvider, PlatformService, FileProvider, ProfilesService, ProfileProvider, SelectorOption, Profile, SelectorService, CommandProvider } from './api'
import { AppService } from './services/app.service' import { AppService } from './services/app.service'
import { ConfigService } from './services/config.service' import { ConfigService } from './services/config.service'
@@ -177,7 +177,7 @@ export default class AppModule { // eslint-disable-line @typescript-eslint/no-ex
if (hotkey.startsWith('profile.')) { if (hotkey.startsWith('profile.')) {
const id = hotkey.substring(hotkey.indexOf('.') + 1) const id = hotkey.substring(hotkey.indexOf('.') + 1)
const profiles = await profilesService.getProfiles() const profiles = await profilesService.getProfiles()
const profile = profiles.find(x => ProfilesService.getProfileHotkeyName(x) === id) const profile = profiles.find(x => AppHotkeyProvider.getProfileHotkeyName(x) === id)
if (profile) { if (profile) {
profilesService.openNewTabForProfile(profile) profilesService.openNewTabForProfile(profile)
} }
@@ -188,10 +188,10 @@ export default class AppModule { // eslint-disable-line @typescript-eslint/no-ex
if (!provider) { if (!provider) {
return return
} }
this.showSelector(provider).catch(() => null) this.showSelector(provider)
} }
if (hotkey === 'command-selector') { if (hotkey === 'command-selector') {
commands.showSelector().catch(() => null) commands.showSelector()
} }
if (hotkey === 'profile-selector') { if (hotkey === 'profile-selector') {
@@ -214,7 +214,7 @@ export default class AppModule { // eslint-disable-line @typescript-eslint/no-ex
callback: () => this.profilesService.openNewTabForProfile(p), callback: () => this.profilesService.openNewTabForProfile(p),
})) }))
if (provider instanceof QuickConnectProfileProvider) { if (provider.supportsQuickConnect) {
options.push({ options.push({
name: this.translate.instant('Quick connect'), name: this.translate.instant('Quick connect'),
freeInputPattern: this.translate.instant('Connect to "%s"...'), freeInputPattern: this.translate.instant('Connect to "%s"...'),

View File

@@ -230,13 +230,11 @@ export class AppService {
if (this._activeTab) { if (this._activeTab) {
this._activeTab.clearActivity() this._activeTab.clearActivity()
this._activeTab.emitBlurred() this._activeTab.emitBlurred()
this._activeTab.emitVisibility(false)
} }
this._activeTab = tab this._activeTab = tab
this.activeTabChange.next(tab) this.activeTabChange.next(tab)
setImmediate(() => { setImmediate(() => {
this._activeTab?.emitFocused() this._activeTab?.emitFocused()
this._activeTab?.emitVisibility(true)
}) })
this.hostWindow.setTitle(this._activeTab?.title) this.hostWindow.setTitle(this._activeTab?.title)
} }

View File

@@ -101,7 +101,7 @@ export class CommandService {
context.tab = tab.getFocusedTab() ?? undefined context.tab = tab.getFocusedTab() ?? undefined
} }
const commands = await this.getCommands(context) const commands = await this.getCommands(context)
return this.selector.show( await this.selector.show(
this.translate.instant('Commands'), this.translate.instant('Commands'),
commands.map(c => ({ commands.map(c => ({
name: c.label, name: c.label,

View File

@@ -10,7 +10,6 @@ import { PlatformService } from '../api/platform'
import { HostAppService } from '../api/hostApp' import { HostAppService } from '../api/hostApp'
import { Vault, VaultService } from './vault.service' import { Vault, VaultService } from './vault.service'
import { serializeFunction } from '../utils' import { serializeFunction } from '../utils'
import { PartialProfileGroup, ProfileGroup } from '../api/profileProvider'
const deepmerge = require('deepmerge') const deepmerge = require('deepmerge')
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
@@ -365,55 +364,6 @@ export class ConfigService {
} }
config.version = 4 config.version = 4
} }
if (config.version < 5) {
const groups: PartialProfileGroup<ProfileGroup>[] = []
for (const p of config.profiles ?? []) {
if (!(p.group ?? '').trim()) {
continue
}
let group = groups.find(x => x.name === p.group)
if (!group) {
group = {
id: `${uuidv4()}`,
name: `${p.group}`,
}
groups.push(group)
}
p.group = group.id
}
const profileGroupCollapsed = JSON.parse(window.localStorage.profileGroupCollapsed ?? '{}')
for (const g of groups) {
if (profileGroupCollapsed[g.name]) {
const collapsed = profileGroupCollapsed[g.name]
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
delete profileGroupCollapsed[g.name]
profileGroupCollapsed[g.id] = collapsed
}
}
window.localStorage.profileGroupCollapsed = JSON.stringify(profileGroupCollapsed)
config.groups = groups
config.version = 5
}
if (config.version < 6) {
if (config.ssh?.clearServiceMessagesOnConnect === false) {
config.profileDefaults ??= {}
config.profileDefaults.ssh ??= {}
config.profileDefaults.ssh.clearServiceMessagesOnConnect = false
delete config.ssh?.clearServiceMessagesOnConnect
}
config.version = 6
}
if (config.version < 7) {
if (!config.configSync?.host || config.configSync?.host === 'https://api.tabby.sh') {
config.configSync ??= {}
delete config.configSync.host
delete config.configSync.token
}
config.version = 7
}
} }
private async maybeDecryptConfig (store) { private async maybeDecryptConfig (store) {

View File

@@ -13,9 +13,8 @@ export class FileProvidersService {
) { } ) { }
async selectAndStoreFile (description: string): Promise<string> { async selectAndStoreFile (description: string): Promise<string> {
return this.selectProvider().then(p => { const p = await this.selectProvider()
return p.selectAndStoreFile(description) return p.selectAndStoreFile(description)
})
} }
async retrieveFile (key: string): Promise<Buffer> { async retrieveFile (key: string): Promise<Buffer> {

View File

@@ -2,15 +2,12 @@ import { Injectable, Inject } from '@angular/core'
import { TranslateService } from '@ngx-translate/core' import { TranslateService } from '@ngx-translate/core'
import { NewTabParameters } from './tabs.service' import { NewTabParameters } from './tabs.service'
import { BaseTabComponent } from '../components/baseTab.component' import { BaseTabComponent } from '../components/baseTab.component'
import { QuickConnectProfileProvider, PartialProfile, PartialProfileGroup, Profile, ProfileGroup, ProfileProvider } from '../api/profileProvider' import { PartialProfile, Profile, ProfileProvider } from '../api/profileProvider'
import { SelectorOption } from '../api/selector' import { SelectorOption } from '../api/selector'
import { AppService } from './app.service' import { AppService } from './app.service'
import { configMerge, ConfigProxy, ConfigService } from './config.service' import { configMerge, ConfigProxy, ConfigService } from './config.service'
import { NotificationsService } from './notifications.service' import { NotificationsService } from './notifications.service'
import { SelectorService } from './selector.service' import { SelectorService } from './selector.service'
import deepClone from 'clone-deep'
import { v4 as uuidv4 } from 'uuid'
import slugify from 'slugify'
@Injectable({ providedIn: 'root' }) @Injectable({ providedIn: 'root' })
export class ProfilesService { export class ProfilesService {
@@ -39,127 +36,6 @@ export class ProfilesService {
@Inject(ProfileProvider) private profileProviders: ProfileProvider<Profile>[], @Inject(ProfileProvider) private profileProviders: ProfileProvider<Profile>[],
) { } ) { }
/*
* Methods used to interract with ProfileProvider
*/
getProviders (): ProfileProvider<Profile>[] {
return [...this.profileProviders]
}
providerForProfile <T extends Profile> (profile: PartialProfile<T>): ProfileProvider<T>|null {
const provider = this.profileProviders.find(x => x.id === profile.type) ?? null
return provider as unknown as ProfileProvider<T>|null
}
getDescription <P extends Profile> (profile: PartialProfile<P>): string|null {
profile = this.getConfigProxyForProfile(profile)
return this.providerForProfile(profile)?.getDescription(profile) ?? null
}
/*
* Methods used to interract with Profile
*/
/*
* Return ConfigProxy for a given Profile
* arg: skipUserDefaults -> do not merge global provider defaults in ConfigProxy
* arg: skipGroupDefaults -> do not merge parent group provider defaults in ConfigProxy
*/
getConfigProxyForProfile <T extends Profile> (profile: PartialProfile<T>, options?: { skipGlobalDefaults?: boolean, skipGroupDefaults?: boolean }): T {
const defaults = this.getProfileDefaults(profile, options).reduce(configMerge, {})
return new ConfigProxy(profile, defaults) as unknown as T
}
/**
* Return an Array of Profiles
* arg: includeBuiltin (default: true) -> include BuiltinProfiles
* arg: clone (default: false) -> return deepclone Array
*/
async getProfiles (options?: { includeBuiltin?: boolean, clone?: boolean }): Promise<PartialProfile<Profile>[]> {
let list = this.config.store.profiles ?? []
if (options?.includeBuiltin ?? true) {
const lists = await Promise.all(this.config.enabledServices(this.profileProviders).map(x => x.getBuiltinProfiles()))
list = [
...this.config.store.profiles ?? [],
...lists.reduce((a, b) => a.concat(b), []),
]
}
const sortKey = p => `${this.resolveProfileGroupName(p.group ?? '')} / ${p.name}`
list.sort((a, b) => sortKey(a).localeCompare(sortKey(b)))
list.sort((a, b) => (a.isBuiltin ? 1 : 0) - (b.isBuiltin ? 1 : 0))
return options?.clone ? deepClone(list) : list
}
/**
* Insert a new Profile in config
* arg: genId (default: true) -> generate uuid in before pushing Profile into config
*/
async newProfile (profile: PartialProfile<Profile>, options?: { genId?: boolean }): Promise<void> {
if (options?.genId ?? true) {
profile.id = `${profile.type}:custom:${slugify(profile.name)}:${uuidv4()}`
}
const cProfile = this.config.store.profiles.find(p => p.id === profile.id)
if (cProfile) {
throw new Error(`Cannot insert new Profile, duplicated Id: ${profile.id}`)
}
this.config.store.profiles.push(profile)
}
/**
* Write a Profile in config
*/
async writeProfile (profile: PartialProfile<Profile>): Promise<void> {
const cProfile = this.config.store.profiles.find(p => p.id === profile.id)
if (cProfile) {
// Fully replace the config
for (const k in cProfile) {
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
delete cProfile[k]
}
Object.assign(cProfile, profile)
}
}
/**
* Delete a Profile from config
*/
async deleteProfile (profile: PartialProfile<Profile>): Promise<void> {
this.providerForProfile(profile)?.deleteProfile(this.getConfigProxyForProfile(profile))
this.config.store.profiles = this.config.store.profiles.filter(p => p.id !== profile.id)
const profileHotkeyName = ProfilesService.getProfileHotkeyName(profile)
if (this.config.store.hotkeys.profile.hasOwnProperty(profileHotkeyName)) {
const profileHotkeys = deepClone(this.config.store.hotkeys.profile)
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
delete profileHotkeys[profileHotkeyName]
this.config.store.hotkeys.profile = profileHotkeys
}
}
/**
* Delete all Profiles from config using option filter
* arg: filter (p: PartialProfile<Profile>) => boolean -> predicate used to decide which profiles have to be deleted
*/
async bulkDeleteProfiles (filter: (p: PartialProfile<Profile>) => boolean): Promise<void> {
for (const profile of this.config.store.profiles.filter(filter)) {
this.providerForProfile(profile)?.deleteProfile(this.getConfigProxyForProfile(profile))
const profileHotkeyName = ProfilesService.getProfileHotkeyName(profile)
if (this.config.store.hotkeys.profile.hasOwnProperty(profileHotkeyName)) {
const profileHotkeys = deepClone(this.config.store.hotkeys.profile)
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
delete profileHotkeys[profileHotkeyName]
this.config.store.hotkeys.profile = profileHotkeys
}
}
this.config.store.profiles = this.config.store.profiles.filter(x => !filter(x))
}
async openNewTabForProfile <P extends Profile> (profile: PartialProfile<P>): Promise<BaseTabComponent|null> { async openNewTabForProfile <P extends Profile> (profile: PartialProfile<P>): Promise<BaseTabComponent|null> {
const params = await this.newTabParametersForProfile(profile) const params = await this.newTabParametersForProfile(profile)
if (params) { if (params) {
@@ -187,40 +63,52 @@ export class ProfilesService {
return params return params
} }
async launchProfile (profile: PartialProfile<Profile>): Promise<void> { getProviders (): ProfileProvider<Profile>[] {
await this.openNewTabForProfile(profile) return [...this.profileProviders]
let recentProfiles: PartialProfile<Profile>[] = JSON.parse(window.localStorage['recentProfiles'] ?? '[]')
if (this.config.store.terminal.showRecentProfiles > 0) {
recentProfiles = recentProfiles.filter(x => x.group !== profile.group || x.name !== profile.name)
recentProfiles.unshift(profile)
recentProfiles = recentProfiles.slice(0, this.config.store.terminal.showRecentProfiles)
} else {
recentProfiles = []
}
window.localStorage['recentProfiles'] = JSON.stringify(recentProfiles)
} }
static getProfileHotkeyName (profile: PartialProfile<Profile>): string { async getProfiles (): Promise<PartialProfile<Profile>[]> {
return (profile.id ?? profile.name).replace(/\./g, '-') const lists = await Promise.all(this.config.enabledServices(this.profileProviders).map(x => x.getBuiltinProfiles()))
let list = lists.reduce((a, b) => a.concat(b), [])
list = [
...this.config.store.profiles ?? [],
...list,
]
const sortKey = p => `${p.group ?? ''} / ${p.name}`
list.sort((a, b) => sortKey(a).localeCompare(sortKey(b)))
list.sort((a, b) => (a.isBuiltin ? 1 : 0) - (b.isBuiltin ? 1 : 0))
return list
} }
/* providerForProfile <T extends Profile> (profile: PartialProfile<T>): ProfileProvider<T>|null {
* Methods used to interract with Profile Selector const provider = this.profileProviders.find(x => x.id === profile.type) ?? null
*/ return provider as unknown as ProfileProvider<T>|null
}
getDescription <P extends Profile> (profile: PartialProfile<P>): string|null {
profile = this.getConfigProxyForProfile(profile)
return this.providerForProfile(profile)?.getDescription(profile) ?? null
}
selectorOptionForProfile <P extends Profile, T> (profile: PartialProfile<P>): SelectorOption<T> { selectorOptionForProfile <P extends Profile, T> (profile: PartialProfile<P>): SelectorOption<T> {
const fullProfile = this.getConfigProxyForProfile(profile) const fullProfile = this.getConfigProxyForProfile(profile)
const provider = this.providerForProfile(fullProfile) const provider = this.providerForProfile(fullProfile)
const freeInputEquivalent = provider instanceof QuickConnectProfileProvider ? provider.intoQuickConnectString(fullProfile) ?? undefined : undefined const freeInputEquivalent = provider?.intoQuickConnectString(fullProfile) ?? undefined
return { return {
...profile, ...profile,
group: this.resolveProfileGroupName(profile.group ?? ''), // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
group: profile.group || '',
freeInputEquivalent, freeInputEquivalent,
description: provider?.getDescription(fullProfile), description: provider?.getDescription(fullProfile),
} }
} }
getRecentProfiles (): PartialProfile<Profile>[] {
let recentProfiles: PartialProfile<Profile>[] = JSON.parse(window.localStorage['recentProfiles'] ?? '[]')
recentProfiles = recentProfiles.slice(0, this.config.store.terminal.showRecentProfiles)
return recentProfiles
}
showProfileSelector (): Promise<PartialProfile<Profile>|null> { showProfileSelector (): Promise<PartialProfile<Profile>|null> {
if (this.selector.active) { if (this.selector.active) {
return Promise.resolve(null) return Promise.resolve(null)
@@ -230,12 +118,12 @@ export class ProfilesService {
try { try {
const recentProfiles = this.getRecentProfiles() const recentProfiles = this.getRecentProfiles()
let options: SelectorOption<void>[] = recentProfiles.map((p, i) => ({ let options: SelectorOption<void>[] = recentProfiles.map(p => ({
...this.selectorOptionForProfile(p), ...this.selectorOptionForProfile(p),
group: this.translate.instant('Recent'), group: this.translate.instant('Recent'),
icon: 'fas fa-history', icon: 'fas fa-history',
color: p.color, color: p.color,
weight: i - (recentProfiles.length + 1), weight: -2,
callback: async () => { callback: async () => {
if (p.id) { if (p.id) {
p = (await this.getProfiles()).find(x => x.id === p.id) ?? p p = (await this.getProfiles()).find(x => x.id === p.id) ?? p
@@ -289,8 +177,7 @@ export class ProfilesService {
}) })
} catch { } } catch { }
this.getProviders().forEach(provider => { this.getProviders().filter(x => x.supportsQuickConnect).forEach(provider => {
if (provider instanceof QuickConnectProfileProvider) {
options.push({ options.push({
name: this.translate.instant('Quick connect'), name: this.translate.instant('Quick connect'),
freeInputPattern: this.translate.instant('Connect to "%s"...'), freeInputPattern: this.translate.instant('Connect to "%s"...'),
@@ -302,25 +189,18 @@ export class ProfilesService {
resolve(profile) resolve(profile)
}, },
}) })
}
}) })
await this.selector.show(this.translate.instant('Select profile or enter an address'), options).catch(() => reject()) await this.selector.show(this.translate.instant('Select profile or enter an address'), options)
} catch (err) { } catch (err) {
reject(err) reject(err)
} }
}) })
} }
getRecentProfiles (): PartialProfile<Profile>[] {
let recentProfiles: PartialProfile<Profile>[] = JSON.parse(window.localStorage['recentProfiles'] ?? '[]')
recentProfiles = recentProfiles.slice(0, this.config.store.terminal.showRecentProfiles)
return recentProfiles
}
async quickConnect (query: string): Promise<PartialProfile<Profile>|null> { async quickConnect (query: string): Promise<PartialProfile<Profile>|null> {
for (const provider of this.getProviders()) { for (const provider of this.getProviders()) {
if (provider instanceof QuickConnectProfileProvider) { if (provider.supportsQuickConnect) {
const profile = provider.quickConnect(query) const profile = provider.quickConnect(query)
if (profile) { if (profile) {
return profile return profile
@@ -331,178 +211,27 @@ export class ProfilesService {
return null return null
} }
/* getConfigProxyForProfile <T extends Profile> (profile: PartialProfile<T>, skipUserDefaults = false): T {
* Methods used to interract with Profile/ProfileGroup/Global defaults
*/
/**
* Return global defaults for a given profile provider
* Always return something, empty object if no defaults found
*/
getProviderDefaults (provider: ProfileProvider<Profile>): any {
const defaults = this.config.store.profileDefaults
return defaults[provider.id] ?? {}
}
/**
* Set global defaults for a given profile provider
*/
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
setProviderDefaults (provider: ProfileProvider<Profile>, pdefaults: any): void {
this.config.store.profileDefaults[provider.id] = pdefaults
}
/**
* Return defaults for a given profile
* Always return something, empty object if no defaults found
* arg: skipUserDefaults -> do not merge global provider defaults in ConfigProxy
* arg: skipGroupDefaults -> do not merge parent group provider defaults in ConfigProxy
*/
getProfileDefaults (profile: PartialProfile<Profile>, options?: { skipGlobalDefaults?: boolean, skipGroupDefaults?: boolean }): any[] {
const provider = this.providerForProfile(profile) const provider = this.providerForProfile(profile)
const defaults = [
return [
this.profileDefaults, this.profileDefaults,
provider?.configDefaults ?? {}, provider?.configDefaults ?? {},
provider && !options?.skipGlobalDefaults ? this.getProviderDefaults(provider) : {}, !provider || skipUserDefaults ? {} : this.config.store.profileDefaults[provider.id] ?? {},
provider && !options?.skipGlobalDefaults && !options?.skipGroupDefaults ? this.getProviderProfileGroupDefaults(profile.group ?? '', provider) : {}, ].reduce(configMerge, {})
] return new ConfigProxy(profile, defaults) as unknown as T
} }
/* async launchProfile (profile: PartialProfile<Profile>): Promise<void> {
* Methods used to interract with ProfileGroup await this.openNewTabForProfile(profile)
*/
/** let recentProfiles: PartialProfile<Profile>[] = JSON.parse(window.localStorage['recentProfiles'] ?? '[]')
* Synchronously return an Array of the existing ProfileGroups if (this.config.store.terminal.showRecentProfiles > 0) {
* Does not return builtin groups recentProfiles = recentProfiles.filter(x => x.group !== profile.group || x.name !== profile.name)
*/ recentProfiles.unshift(profile)
getSyncProfileGroups (): PartialProfileGroup<ProfileGroup>[] { recentProfiles = recentProfiles.slice(0, this.config.store.terminal.showRecentProfiles)
return deepClone(this.config.store.groups ?? [])
}
/**
* Return an Array of the existing ProfileGroups
* arg: includeProfiles (default: false) -> if false, does not fill up the profiles field of ProfileGroup
* arg: includeNonUserGroup (default: false) -> if false, does not add built-in and ungrouped groups
*/
async getProfileGroups (options?: { includeProfiles?: boolean, includeNonUserGroup?: boolean }): Promise<PartialProfileGroup<ProfileGroup>[]> {
let profiles: PartialProfile<Profile>[] = []
if (options?.includeProfiles) {
profiles = await this.getProfiles({ includeBuiltin: options.includeNonUserGroup, clone: true })
}
let groups: PartialProfileGroup<ProfileGroup>[] = this.getSyncProfileGroups()
groups = groups.map(x => {
x.editable = true
if (options?.includeProfiles) {
x.profiles = profiles.filter(p => p.group === x.id)
profiles = profiles.filter(p => p.group !== x.id)
}
return x
})
if (options?.includeNonUserGroup) {
const builtInGroups: PartialProfileGroup<ProfileGroup>[] = []
builtInGroups.push({
id: 'built-in',
name: this.translate.instant('Built-in'),
editable: false,
profiles: [],
})
const ungrouped: PartialProfileGroup<ProfileGroup> = {
id: 'ungrouped',
name: this.translate.instant('Ungrouped'),
editable: false,
}
if (options.includeProfiles) {
for (const profile of profiles.filter(p => p.isBuiltin)) {
let group: PartialProfileGroup<ProfileGroup> | undefined = builtInGroups.find(g => g.id === slugify(profile.group ?? 'built-in'))
if (!group) {
group = {
id: `${slugify(profile.group!)}`,
name: `${profile.group!}`,
editable: false,
profiles: [],
}
builtInGroups.push(group)
}
group.profiles!.push(profile)
}
ungrouped.profiles = profiles.filter(p => !p.isBuiltin)
}
groups = groups.concat(builtInGroups)
groups.push(ungrouped)
}
return groups
}
/**
* Insert a new ProfileGroup in config
* arg: genId (default: true) -> generate uuid in before pushing Profile into config
*/
async newProfileGroup (group: PartialProfileGroup<ProfileGroup>, options?: { genId?: boolean }): Promise<void> {
if (options?.genId ?? true) {
group.id = `${uuidv4()}`
}
const cProfileGroup = this.config.store.groups.find(p => p.id === group.id)
if (cProfileGroup) {
throw new Error(`Cannot insert new ProfileGroup, duplicated Id: ${group.id}`)
}
this.config.store.groups.push(group)
}
/**
* Write a ProfileGroup in config
*/
async writeProfileGroup (group: PartialProfileGroup<ProfileGroup>): Promise<void> {
delete group.profiles
delete group.editable
const cGroup = this.config.store.groups.find(g => g.id === group.id)
if (cGroup) {
Object.assign(cGroup, group)
}
}
/**
* Delete a ProfileGroup from config
*/
async deleteProfileGroup (group: PartialProfileGroup<ProfileGroup>, options?: { deleteProfiles?: boolean }): Promise<void> {
this.config.store.groups = this.config.store.groups.filter(g => g.id !== group.id)
if (options?.deleteProfiles) {
await this.bulkDeleteProfiles((p) => p.group === group.id)
} else { } else {
for (const profile of this.config.store.profiles.filter(x => x.group === group.id)) { recentProfiles = []
delete profile.group }
window.localStorage['recentProfiles'] = JSON.stringify(recentProfiles)
} }
} }
}
/**
* Resolve and return ProfileGroup Name from ProfileGroup ID
*/
resolveProfileGroupName (groupId: string): string {
return this.config.store.groups.find(g => g.id === groupId)?.name ?? groupId
}
/**
* Return defaults for a given group ID and provider
* Always return something, empty object if no defaults found
* arg: skipUserDefaults -> do not merge global provider defaults in ConfigProxy
*/
getProviderProfileGroupDefaults (groupId: string, provider: ProfileProvider<Profile>): any {
return this.getSyncProfileGroups().find(g => g.id === groupId)?.defaults?.[provider.id] ?? {}
}
}

View File

@@ -3,7 +3,7 @@ import { Subject, Observable } from 'rxjs'
import * as Color from 'color' import * as Color from 'color'
import { ConfigService } from '../services/config.service' import { ConfigService } from '../services/config.service'
import { Theme } from '../api/theme' import { Theme } from '../api/theme'
import { PlatformService, PlatformTheme } from '../api/platform' import { PlatformService } from '../api/platform'
import { NewTheme } from '../theme' import { NewTheme } from '../theme'
@Injectable({ providedIn: 'root' }) @Injectable({ providedIn: 'root' })
@@ -194,14 +194,7 @@ export class ThemesService {
/// @hidden /// @hidden
_getActiveColorScheme (): any { _getActiveColorScheme (): any {
let theme: PlatformTheme = 'dark' if (this.platform.getTheme() === 'light') {
if (this.config.store.appearance.colorSchemeMode === 'light') {
theme = 'light'
} else if (this.config.store.appearance.colorSchemeMode === 'auto') {
theme = this.platform.getTheme()
}
if (theme === 'light') {
return this.config.store.terminal.lightColorScheme return this.config.store.terminal.lightColorScheme
} else { } else {
return this.config.store.terminal.colorScheme return this.config.store.terminal.colorScheme

View File

@@ -285,7 +285,7 @@ export class VaultFileProvider extends FileProvider {
icon: 'fas fa-file', icon: 'fas fa-file',
result: f, result: f,
})), })),
]).catch(() => null) ])
if (result) { if (result) {
return `${this.prefix}${result.key.id}` return `${this.prefix}${result.key.id}`
} }

View File

@@ -149,7 +149,7 @@ export class CommonOptionsContextMenu extends TabContextMenuItemProvider {
click: async () => { click: async () => {
const modal = this.ngbModal.open(PromptModalComponent) const modal = this.ngbModal.open(PromptModalComponent)
modal.componentInstance.prompt = this.translate.instant('Profile name') modal.componentInstance.prompt = this.translate.instant('Profile name')
const name = (await modal.result.catch(() => null))?.value const name = (await modal.result)?.value
if (!name) { if (!name) {
return return
} }
@@ -262,7 +262,7 @@ export class ProfilesContextMenu extends TabContextMenuItemProvider {
} }
async switchTabProfile (tab: BaseTabComponent) { async switchTabProfile (tab: BaseTabComponent) {
const profile = await this.profilesService.showProfileSelector().catch(() => null) const profile = await this.profilesService.showProfileSelector()
if (!profile) { if (!profile) {
return return
} }

View File

@@ -22,6 +22,5 @@ export class ElectronConfigProvider extends ConfigProvider {
}, },
}, },
} }
defaults = {} defaults = {}
} }

View File

@@ -11,7 +11,6 @@ import { ElectronHostWindow } from './hostWindow.service'
import { ShellIntegrationService } from './shellIntegration.service' import { ShellIntegrationService } from './shellIntegration.service'
import { ElectronHostAppService } from './hostApp.service' import { ElectronHostAppService } from './hostApp.service'
import { PlatformTheme } from '../../../tabby-core/src/api/platform' import { PlatformTheme } from '../../../tabby-core/src/api/platform'
import { configPath } from '../../../app/lib/config'
const fontManager = require('fontmanager-redux') // eslint-disable-line const fontManager = require('fontmanager-redux') // eslint-disable-line
/* eslint-disable block-scoped-var */ /* eslint-disable block-scoped-var */
@@ -37,7 +36,7 @@ export class ElectronPlatformService extends PlatformService {
private translate: TranslateService, private translate: TranslateService,
) { ) {
super() super()
this.configPath = configPath this.configPath = path.join(electron.app.getPath('userData'), 'config.yaml')
electron.ipcRenderer.on('host:display-metrics-changed', () => { electron.ipcRenderer.on('host:display-metrics-changed', () => {
this.zone.run(() => this.displayMetricsChanged.next()) this.zone.run(() => this.displayMetricsChanged.next())

View File

@@ -33,7 +33,6 @@ export class ShellIntegrationService {
command: 'paste "%V"', command: 'paste "%V"',
}, },
] ]
private constructor ( private constructor (
private electron: ElectronService, private electron: ElectronService,
private hostApp: HostAppService, private hostApp: HostAppService,

View File

@@ -70,7 +70,6 @@ export class PluginManagerService {
map(plugins => { map(plugins => {
const mapping: Record<string, PluginInfo[]> = {} const mapping: Record<string, PluginInfo[]> = {}
for (const p of plugins) { for (const p of plugins) {
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
mapping[p.name] ??= [] mapping[p.name] ??= []
mapping[p.name].push(p) mapping[p.name].push(p)
} }

View File

@@ -3,10 +3,10 @@ import { SerialPortStream } from '@serialport/stream'
import { LogService, NotificationsService } from 'tabby-core' import { LogService, NotificationsService } from 'tabby-core'
import { Subject, Observable } from 'rxjs' import { Subject, Observable } from 'rxjs'
import { Injector, NgZone } from '@angular/core' import { Injector, NgZone } from '@angular/core'
import { BaseSession, ConnectableTerminalProfile, InputProcessingOptions, InputProcessor, LoginScriptsOptions, SessionMiddleware, StreamProcessingOptions, TerminalStreamProcessor, UTF8SplitterMiddleware } from 'tabby-terminal' import { BaseSession, BaseTerminalProfile, InputProcessingOptions, InputProcessor, LoginScriptsOptions, SessionMiddleware, StreamProcessingOptions, TerminalStreamProcessor, UTF8SplitterMiddleware } from 'tabby-terminal'
import { SerialService } from './services/serial.service' import { SerialService } from './services/serial.service'
export interface SerialProfile extends ConnectableTerminalProfile { export interface SerialProfile extends BaseTerminalProfile {
options: SerialProfileOptions options: SerialProfileOptions
} }

View File

@@ -87,11 +87,6 @@ ul.nav-tabs(ngbNav, #nav='ngbNav')
.description(translate) Sends data one byte at a time .description(translate) Sends data one byte at a time
toggle([(ngModel)]='profile.options.slowSend') toggle([(ngModel)]='profile.options.slowSend')
li(ngbNavItem)
a(ngbNavLink, translate) Colors
ng-template(ngbNavContent)
color-scheme-selector([(model)]='profile.terminalColorScheme')
li(ngbNavItem) li(ngbNavItem)
a(ngbNavLink, translate) Login scripts a(ngbNavLink, translate) Login scripts
ng-template(ngbNavContent) ng-template(ngbNavContent)

View File

@@ -2,14 +2,14 @@ import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'
import slugify from 'slugify' import slugify from 'slugify'
import deepClone from 'clone-deep' import deepClone from 'clone-deep'
import { Injectable } from '@angular/core' import { Injectable } from '@angular/core'
import { NewTabParameters, SelectorService, HostAppService, Platform, TranslateService, ConnectableProfileProvider } from 'tabby-core' import { ProfileProvider, NewTabParameters, SelectorService, HostAppService, Platform, TranslateService } from 'tabby-core'
import { SerialProfileSettingsComponent } from './components/serialProfileSettings.component' import { SerialProfileSettingsComponent } from './components/serialProfileSettings.component'
import { SerialTabComponent } from './components/serialTab.component' import { SerialTabComponent } from './components/serialTab.component'
import { SerialService } from './services/serial.service' import { SerialService } from './services/serial.service'
import { BAUD_RATES, SerialProfile } from './api' import { BAUD_RATES, SerialProfile } from './api'
@Injectable({ providedIn: 'root' }) @Injectable({ providedIn: 'root' })
export class SerialProfilesService extends ConnectableProfileProvider<SerialProfile> { export class SerialProfilesService extends ProfileProvider<SerialProfile> {
id = 'serial' id = 'serial'
name = _('Serial') name = _('Serial')
settingsComponent = SerialProfileSettingsComponent settingsComponent = SerialProfileSettingsComponent
@@ -32,7 +32,6 @@ export class SerialProfilesService extends ConnectableProfileProvider<SerialProf
slowSend: false, slowSend: false,
input: { backspace: 'backspace' }, input: { backspace: 'backspace' },
}, },
clearServiceMessagesOnConnect: false,
} }
constructor ( constructor (

View File

@@ -20,7 +20,7 @@ ul.nav-tabs(ngbNav, #nav='ngbNav')
) )
i.fas.fa-external-link-alt i.fas.fa-external-link-alt
.form-line(*ngIf='config.store.configSync.token') .form-line
.header .header
.title(translate) Secret sync token .title(translate) Secret sync token
.description(translate) Get it from the Tabby Web settings window .description(translate) Get it from the Tabby Web settings window
@@ -36,11 +36,6 @@ ul.nav-tabs(ngbNav, #nav='ngbNav')
i.fas.fa-fw.fa-check.text-success(*ngIf='connectionSuccessful') i.fas.fa-fw.fa-check.text-success(*ngIf='connectionSuccessful')
i.fas.fa-fw.fa-exclamation-triangle.text-danger(*ngIf='connectionSuccessful === false') i.fas.fa-fw.fa-exclamation-triangle.text-danger(*ngIf='connectionSuccessful === false')
.alert.alert-info.d-flex.align-items-center
.me-auto
span(translate) Config sync requires an instance of the Tabby Web service.
a.ml-1((click)='openTabbyWebInfo()', href='#', translate) Learn more
ng-container(*ngIf='config.store.configSync.token') ng-container(*ngIf='config.store.configSync.token')
.alert.alert-danger(*ngIf='connectionSuccessful === false') .alert.alert-danger(*ngIf='connectionSuccessful === false')
i.fas.fa-exclamation-triangle i.fas.fa-exclamation-triangle

View File

@@ -59,7 +59,7 @@ export class ConfigSyncSettingsTabComponent extends BaseComponent {
const modal = this.ngbModal.open(PromptModalComponent) const modal = this.ngbModal.open(PromptModalComponent)
modal.componentInstance.prompt = this.translate.instant('Name for the new config') modal.componentInstance.prompt = this.translate.instant('Name for the new config')
modal.componentInstance.value = name modal.componentInstance.value = name
name = (await modal.result.catch(() => null))?.value name = (await modal.result)?.value
if (!name) { if (!name) {
return return
} }
@@ -141,8 +141,4 @@ export class ConfigSyncSettingsTabComponent extends BaseComponent {
this.platform.openExternal(this.config.store.configSync.host) this.platform.openExternal(this.config.store.configSync.host)
} }
} }
openTabbyWebInfo () {
this.platform.openExternal('https://github.com/Eugeny/tabby-web')
}
} }

View File

@@ -1,32 +0,0 @@
.modal-header
h3.m-0 {{group.name}}
.modal-body
.row
.col-12.col-lg-4
.mb-3
label(translate) Name
input.form-control(
type='text',
autofocus,
[(ngModel)]='group.name',
)
.col-12.col-lg-8
.form-line.content-box
.header
.title(translate) Default profile group settings
.description(translate) These apply to all profiles of a given type in this group
.list-group.mt-3.mb-3.content-box
a.list-group-item.list-group-item-action.d-flex.align-items-center(
(click)='editDefaults(provider)',
*ngFor='let provider of providers'
) {{provider.name|translate}}
.me-auto
button.btn.btn-link.hover-reveal.ms-1((click)='$event.stopPropagation(); deleteDefaults(provider)')
i.fas.fa-trash-arrow-up
.modal-footer
button.btn.btn-primary((click)='save()', translate) Save
button.btn.btn-danger((click)='cancel()', translate) Cancel

View File

@@ -1,54 +0,0 @@
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import { Component, Input } from '@angular/core'
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'
import { ConfigProxy, ProfileGroup, Profile, ProfileProvider, PlatformService, TranslateService } from 'tabby-core'
/** @hidden */
@Component({
templateUrl: './editProfileGroupModal.component.pug',
})
export class EditProfileGroupModalComponent<G extends ProfileGroup> {
@Input() group: G & ConfigProxy
@Input() providers: ProfileProvider<Profile>[]
constructor (
private modalInstance: NgbActiveModal,
private platform: PlatformService,
private translate: TranslateService,
) {}
save () {
this.modalInstance.close({ group: this.group })
}
cancel () {
this.modalInstance.dismiss()
}
editDefaults (provider: ProfileProvider<Profile>) {
this.modalInstance.close({ group: this.group, provider })
}
async deleteDefaults (provider: ProfileProvider<Profile>): Promise<void> {
if ((await this.platform.showMessageBox(
{
type: 'warning',
message: this.translate.instant('Restore settings to inherited defaults ?'),
buttons: [
this.translate.instant('Delete'),
this.translate.instant('Keep'),
],
defaultId: 1,
cancelId: 1,
},
)).response === 0) {
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
delete this.group.defaults?.[provider.id]
}
}
}
export interface EditProfileGroupModalComponentResult<G extends ProfileGroup> {
group: G
provider?: ProfileProvider<Profile>
}

View File

@@ -1,7 +1,7 @@
.modal-header(*ngIf='defaultsMode === "disabled"') .modal-header(*ngIf='!defaultsMode')
h3.m-0 {{profile.name}} h3.m-0 {{profile.name}}
.modal-header(*ngIf='defaultsMode !== "disabled"') .modal-header(*ngIf='defaultsMode')
h3.m-0( h3.m-0(
translate='Defaults for {type}', translate='Defaults for {type}',
[translateParams]='{type: profileProvider.name}' [translateParams]='{type: profileProvider.name}'
@@ -10,7 +10,7 @@
.modal-body .modal-body
.row .row
.col-12.col-lg-4 .col-12.col-lg-4
.mb-3(*ngIf='defaultsMode === "disabled"') .mb-3(*ngIf='!defaultsMode')
label(translate) Name label(translate) Name
input.form-control( input.form-control(
type='text', type='text',
@@ -18,20 +18,17 @@
[(ngModel)]='profile.name', [(ngModel)]='profile.name',
) )
.mb-3(*ngIf='defaultsMode === "disabled"') .mb-3(*ngIf='!defaultsMode')
label(translate) Group label(translate) Group
input.form-control( input.form-control(
type='text', type='text',
alwaysVisibleTypeahead, alwaysVisibleTypeahead,
placeholder='Ungrouped', placeholder='Ungrouped',
[(ngModel)]='profileGroup', [(ngModel)]='profile.group',
[ngbTypeahead]='groupTypeahead', [ngbTypeahead]='groupTypeahead',
[inputFormatter]="groupFormatter",
[resultFormatter]="groupFormatter",
[editable]="false"
) )
.mb-3(*ngIf='defaultsMode === "disabled"') .mb-3(*ngIf='!defaultsMode')
label(translate) Icon label(translate) Icon
.input-group .input-group
input.form-control( input.form-control(
@@ -77,15 +74,9 @@
) )
option(ngValue='auto', translate) Auto option(ngValue='auto', translate) Auto
option(ngValue='keep', translate) Keep option(ngValue='keep', translate) Keep
option(*ngIf='isConnectable()', ngValue='reconnect', translate) Reconnect option(*ngIf='profile.type == "serial" || profile.type == "telnet" || profile.type == "ssh"', ngValue='reconnect', translate) Reconnect
option(ngValue='close', translate) Close option(ngValue='close', translate) Close
.form-line(*ngIf='isConnectable()')
.header
.title(translate) Clear terminal after connection
toggle(
[(ngModel)]='profile.clearServiceMessagesOnConnect',
)
.mb-4 .mb-4
.col-12.col-lg-8(*ngIf='this.profileProvider.settingsComponent') .col-12.col-lg-8(*ngIf='this.profileProvider.settingsComponent')

View File

@@ -2,7 +2,7 @@
import { Observable, OperatorFunction, debounceTime, map, distinctUntilChanged } from 'rxjs' import { Observable, OperatorFunction, debounceTime, map, distinctUntilChanged } from 'rxjs'
import { Component, Input, ViewChild, ViewContainerRef, ComponentFactoryResolver, Injector } from '@angular/core' import { Component, Input, ViewChild, ViewContainerRef, ComponentFactoryResolver, Injector } from '@angular/core'
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap' import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'
import { ConfigProxy, PartialProfileGroup, Profile, ProfileProvider, ProfileSettingsComponent, ProfilesService, TAB_COLORS, ProfileGroup, ConnectableProfileProvider } from 'tabby-core' import { ConfigProxy, ConfigService, Profile, ProfileProvider, ProfileSettingsComponent, ProfilesService, TAB_COLORS } from 'tabby-core'
const iconsData = require('../../../tabby-core/src/icons.json') const iconsData = require('../../../tabby-core/src/icons.json')
const iconsClassList = Object.keys(iconsData).map( const iconsClassList = Object.keys(iconsData).map(
@@ -19,9 +19,8 @@ export class EditProfileModalComponent<P extends Profile> {
@Input() profile: P & ConfigProxy @Input() profile: P & ConfigProxy
@Input() profileProvider: ProfileProvider<P> @Input() profileProvider: ProfileProvider<P>
@Input() settingsComponent: new () => ProfileSettingsComponent<P> @Input() settingsComponent: new () => ProfileSettingsComponent<P>
@Input() defaultsMode: 'enabled'|'group'|'disabled' = 'disabled' @Input() defaultsMode = false
@Input() profileGroup: PartialProfileGroup<ProfileGroup> | undefined groupNames: string[]
groups: PartialProfileGroup<ProfileGroup>[]
@ViewChild('placeholder', { read: ViewContainerRef }) placeholder: ViewContainerRef @ViewChild('placeholder', { read: ViewContainerRef }) placeholder: ViewContainerRef
private _profile: Profile private _profile: Profile
@@ -31,14 +30,14 @@ export class EditProfileModalComponent<P extends Profile> {
private injector: Injector, private injector: Injector,
private componentFactoryResolver: ComponentFactoryResolver, private componentFactoryResolver: ComponentFactoryResolver,
private profilesService: ProfilesService, private profilesService: ProfilesService,
config: ConfigService,
private modalInstance: NgbActiveModal, private modalInstance: NgbActiveModal,
) { ) {
if (this.defaultsMode === 'disabled') { this.groupNames = [...new Set(
this.profilesService.getProfileGroups().then(groups => { (config.store.profiles as Profile[])
this.groups = groups .map(x => x.group)
this.profileGroup = groups.find(g => g.id === this.profile.group) .filter(x => !!x),
}) )].sort() as string[]
}
} }
colorsAutocomplete = text$ => text$.pipe( colorsAutocomplete = text$ => text$.pipe(
@@ -57,7 +56,7 @@ export class EditProfileModalComponent<P extends Profile> {
ngOnInit () { ngOnInit () {
this._profile = this.profile this._profile = this.profile
this.profile = this.profilesService.getConfigProxyForProfile(this.profile, { skipGlobalDefaults: this.defaultsMode === 'enabled', skipGroupDefaults: this.defaultsMode === 'group' }) this.profile = this.profilesService.getConfigProxyForProfile(this.profile, this.defaultsMode)
} }
ngAfterViewInit () { ngAfterViewInit () {
@@ -73,15 +72,13 @@ export class EditProfileModalComponent<P extends Profile> {
} }
} }
groupTypeahead: OperatorFunction<string, readonly PartialProfileGroup<ProfileGroup>[]> = (text$: Observable<string>) => groupTypeahead = (text$: Observable<string>) =>
text$.pipe( text$.pipe(
debounceTime(200), debounceTime(200),
distinctUntilChanged(), distinctUntilChanged(),
map(q => this.groups.filter(g => !q || g.name.toLowerCase().includes(q.toLowerCase()))), map(q => this.groupNames.filter(x => !q || x.toLowerCase().includes(q.toLowerCase()))),
) )
groupFormatter = (g: PartialProfileGroup<ProfileGroup>) => g.name
iconSearch: OperatorFunction<string, string[]> = (text$: Observable<string>) => iconSearch: OperatorFunction<string, string[]> = (text$: Observable<string>) =>
text$.pipe( text$.pipe(
debounceTime(200), debounceTime(200),
@@ -89,12 +86,7 @@ export class EditProfileModalComponent<P extends Profile> {
) )
save () { save () {
if (!this.profileGroup) { this.profile.group ||= undefined
this.profile.group = undefined
} else {
this.profile.group = this.profileGroup.id
}
this.settingsComponentInstance?.save?.() this.settingsComponentInstance?.save?.()
this.profile.__cleanup() this.profile.__cleanup()
this.modalInstance.close(this._profile) this.modalInstance.close(this._profile)
@@ -103,9 +95,4 @@ export class EditProfileModalComponent<P extends Profile> {
cancel () { cancel () {
this.modalInstance.dismiss() this.modalInstance.dismiss()
} }
isConnectable (): boolean {
return this.profileProvider instanceof ConnectableProfileProvider
}
} }

View File

@@ -12,12 +12,10 @@ ul.nav-tabs(ngbNav, #nav='ngbNav')
[(ngModel)]='config.store.terminal.profile', [(ngModel)]='config.store.terminal.profile',
(ngModelChange)='config.save()', (ngModelChange)='config.save()',
) )
optgroup([label]='"Custom Profiles"|translate', *ngIf='customProfiles?.length > 0')
option( option(
*ngFor='let profile of customProfiles', *ngFor='let profile of profiles',
[ngValue]='profile.id' [ngValue]='profile.id'
) {{profile.name}} ) {{profile.name}}
optgroup([label]='"Built-in Profiles"|translate')
option( option(
*ngFor='let profile of builtinProfiles', *ngFor='let profile of builtinProfiles',
[ngValue]='profile.id' [ngValue]='profile.id'
@@ -29,17 +27,9 @@ ul.nav-tabs(ngbNav, #nav='ngbNav')
i.fas.fa-fw.fa-search i.fas.fa-fw.fa-search
input.form-control(type='search', [placeholder]='"Filter"|translate', [(ngModel)]='filter') input.form-control(type='search', [placeholder]='"Filter"|translate', [(ngModel)]='filter')
div(ngbDropdown).d-inline-block.flex-shrink-0.ms-3 button.btn.btn-primary.flex-shrink-0.ms-3((click)='newProfile()')
button.btn.btn-primary(ngbDropdownToggle)
i.fas.fa-fw.fa-plus
span(translate) New
div(ngbDropdownMenu)
button(ngbDropdownItem, (click)='newProfile()')
i.fas.fa-fw.fa-plus i.fas.fa-fw.fa-plus
span(translate) New profile span(translate) New profile
button(ngbDropdownItem, (click)='newProfileGroup()')
i.fas.fa-fw.fa-plus
span(translate) New profile Group
.list-group.mt-3.mb-3 .list-group.mt-3.mb-3
ng-container(*ngFor='let group of profileGroups') ng-container(*ngFor='let group of profileGroups')
@@ -47,17 +37,17 @@ ul.nav-tabs(ngbNav, #nav='ngbNav')
.list-group-item.list-group-item-action.d-flex.align-items-center( .list-group-item.list-group-item-action.d-flex.align-items-center(
(click)='toggleGroupCollapse(group)' (click)='toggleGroupCollapse(group)'
) )
.fa.fa-fw.fa-chevron-right(*ngIf='group.collapsed && group.profiles?.length > 0') .fa.fa-fw.fa-chevron-right(*ngIf='group.collapsed')
.fa.fa-fw.fa-chevron-down(*ngIf='!group.collapsed && group.profiles?.length > 0') .fa.fa-fw.fa-chevron-down(*ngIf='!group.collapsed')
span.ms-3.me-auto {{group.name || ("Ungrouped"|translate)}} span.ms-3.me-auto {{group.name || ("Ungrouped"|translate)}}
button.btn.btn-sm.btn-link.hover-reveal.ms-2( button.btn.btn-sm.btn-link.hover-reveal.ms-2(
*ngIf='group.editable && group.name', *ngIf='group.editable && group.name',
(click)='$event.stopPropagation(); editProfileGroup(group)' (click)='$event.stopPropagation(); editGroup(group)'
) )
i.fas.fa-pencil-alt i.fas.fa-pencil-alt
button.btn.btn-sm.btn-link.hover-reveal.ms-2( button.btn.btn-sm.btn-link.hover-reveal.ms-2(
*ngIf='group.editable && group.name', *ngIf='group.editable && group.name',
(click)='$event.stopPropagation(); deleteProfileGroup(group)' (click)='$event.stopPropagation(); deleteGroup(group)'
) )
i.fas.fa-trash-alt i.fas.fa-trash-alt
ng-container(*ngIf='!group.collapsed') ng-container(*ngIf='!group.collapsed')
@@ -77,7 +67,7 @@ ul.nav-tabs(ngbNav, #nav='ngbNav')
.me-auto .me-auto
button.btn.btn-link.hover-reveal.ms-1(*ngIf='!profile.isTemplate', (click)='$event.stopPropagation(); launchProfile(profile)') button.btn.btn-link.hover-reveal.ms-1((click)='$event.stopPropagation(); launchProfile(profile)')
i.fas.fa-play i.fas.fa-play
.ms-1.hover-reveal(ngbDropdown, placement='bottom-right top-right auto') .ms-1.hover-reveal(ngbDropdown, placement='bottom-right top-right auto')
@@ -179,12 +169,9 @@ ul.nav-tabs(ngbNav, #nav='ngbNav')
.description(translate) These apply to all profiles of a given type .description(translate) These apply to all profiles of a given type
.list-group.mt-3.mb-3.content-box .list-group.mt-3.mb-3.content-box
a.list-group-item.list-group-item-action.d-flex.align-items-center( a.list-group-item.list-group-item-action(
(click)='editDefaults(provider)', (click)='editDefaults(provider)',
*ngFor='let provider of profileProviders' *ngFor='let provider of profileProviders'
) {{provider.name|translate}} ) {{provider.name|translate}}
.me-auto
button.btn.btn-link.hover-reveal.ms-1((click)='$event.stopPropagation(); deleteDefaults(provider)')
i.fas.fa-trash-arrow-up
div([ngbNavOutlet]='nav') div([ngbNavOutlet]='nav')

View File

@@ -1,29 +1,32 @@
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker' import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'
import { v4 as uuidv4 } from 'uuid'
import slugify from 'slugify'
import deepClone from 'clone-deep' import deepClone from 'clone-deep'
import { Component, Inject } from '@angular/core' import { Component, Inject } from '@angular/core'
import { NgbModal } from '@ng-bootstrap/ng-bootstrap' import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
import { ConfigService, HostAppService, Profile, SelectorService, ProfilesService, PromptModalComponent, PlatformService, BaseComponent, PartialProfile, ProfileProvider, TranslateService, Platform, ProfileGroup, PartialProfileGroup, QuickConnectProfileProvider } from 'tabby-core' import { ConfigService, HostAppService, Profile, SelectorService, ProfilesService, PromptModalComponent, PlatformService, BaseComponent, PartialProfile, ProfileProvider, TranslateService, Platform, AppHotkeyProvider } from 'tabby-core'
import { EditProfileModalComponent } from './editProfileModal.component' import { EditProfileModalComponent } from './editProfileModal.component'
import { EditProfileGroupModalComponent, EditProfileGroupModalComponentResult } from './editProfileGroupModal.component'
interface ProfileGroup {
name?: string
profiles: PartialProfile<Profile>[]
editable: boolean
collapsed: boolean
}
_('Filter') _('Filter')
_('Ungrouped') _('Ungrouped')
interface CollapsableProfileGroup extends ProfileGroup {
collapsed: boolean
}
/** @hidden */ /** @hidden */
@Component({ @Component({
templateUrl: './profilesSettingsTab.component.pug', templateUrl: './profilesSettingsTab.component.pug',
styleUrls: ['./profilesSettingsTab.component.scss'], styleUrls: ['./profilesSettingsTab.component.scss'],
}) })
export class ProfilesSettingsTabComponent extends BaseComponent { export class ProfilesSettingsTabComponent extends BaseComponent {
builtinProfiles: PartialProfile<Profile>[] = []
profiles: PartialProfile<Profile>[] = [] profiles: PartialProfile<Profile>[] = []
builtinProfiles: PartialProfile<Profile>[] = []
templateProfiles: PartialProfile<Profile>[] = [] templateProfiles: PartialProfile<Profile>[] = []
customProfiles: PartialProfile<Profile>[] = [] profileGroups: ProfileGroup[]
profileGroups: PartialProfileGroup<CollapsableProfileGroup>[]
filter = '' filter = ''
Platform = Platform Platform = Platform
@@ -42,17 +45,12 @@ export class ProfilesSettingsTabComponent extends BaseComponent {
} }
async ngOnInit (): Promise<void> { async ngOnInit (): Promise<void> {
await this.refreshProfileGroups() this.refresh()
await this.refreshProfiles()
this.subscribeUntilDestroyed(this.config.changed$, () => this.refreshProfileGroups())
this.subscribeUntilDestroyed(this.config.changed$, () => this.refreshProfiles())
}
async refreshProfiles (): Promise<void> {
this.builtinProfiles = (await this.profilesService.getProfiles()).filter(x => x.isBuiltin) this.builtinProfiles = (await this.profilesService.getProfiles()).filter(x => x.isBuiltin)
this.customProfiles = (await this.profilesService.getProfiles()).filter(x => !x.isBuiltin)
this.templateProfiles = this.builtinProfiles.filter(x => x.isTemplate) this.templateProfiles = this.builtinProfiles.filter(x => x.isTemplate)
this.builtinProfiles = this.builtinProfiles.filter(x => !x.isTemplate) this.builtinProfiles = this.builtinProfiles.filter(x => !x.isTemplate)
this.refresh()
this.subscribeUntilDestroyed(this.config.changed$, () => this.refresh())
} }
launchProfile (profile: PartialProfile<Profile>): void { launchProfile (profile: PartialProfile<Profile>): void {
@@ -61,7 +59,7 @@ export class ProfilesSettingsTabComponent extends BaseComponent {
async newProfile (base?: PartialProfile<Profile>): Promise<void> { async newProfile (base?: PartialProfile<Profile>): Promise<void> {
if (!base) { if (!base) {
let profiles = await this.profilesService.getProfiles() let profiles = [...this.templateProfiles, ...this.builtinProfiles, ...this.profiles]
profiles = profiles.filter(x => !this.isProfileBlacklisted(x)) profiles = profiles.filter(x => !this.isProfileBlacklisted(x))
profiles.sort((a, b) => (a.weight ?? 0) - (b.weight ?? 0)) profiles.sort((a, b) => (a.weight ?? 0) - (b.weight ?? 0))
base = await this.selector.show( base = await this.selector.show(
@@ -69,32 +67,31 @@ export class ProfilesSettingsTabComponent extends BaseComponent {
profiles.map(p => ({ profiles.map(p => ({
icon: p.icon, icon: p.icon,
description: this.profilesService.getDescription(p) ?? undefined, description: this.profilesService.getDescription(p) ?? undefined,
name: p.group ? `${this.profilesService.resolveProfileGroupName(p.group)} / ${p.name}` : p.name, name: p.group ? `${p.group} / ${p.name}` : p.name,
result: p, result: p,
})), })),
).catch(() => undefined) )
if (!base) {
return
} }
} const profile: PartialProfile<Profile> = deepClone(base)
const baseProfile: PartialProfile<Profile> = deepClone(base) delete profile.id
delete baseProfile.id
if (base.isTemplate) { if (base.isTemplate) {
baseProfile.name = '' profile.name = ''
} else if (!base.isBuiltin) { } else if (!base.isBuiltin) {
baseProfile.name = this.translate.instant('{name} copy', base) profile.name = this.translate.instant('{name} copy', base)
} }
baseProfile.isBuiltin = false profile.isBuiltin = false
baseProfile.isTemplate = false profile.isTemplate = false
const result = await this.showProfileEditModal(baseProfile) const result = await this.showProfileEditModal(profile)
if (!result) { if (!result) {
return return
} }
if (!result.name) { Object.assign(profile, result)
const cfgProxy = this.profilesService.getConfigProxyForProfile(result) if (!profile.name) {
result.name = this.profilesService.providerForProfile(result)?.getSuggestedName(cfgProxy) ?? this.translate.instant('{name} copy', base) const cfgProxy = this.profilesService.getConfigProxyForProfile(profile)
profile.name = this.profilesService.providerForProfile(profile)?.getSuggestedName(cfgProxy) ?? this.translate.instant('{name} copy', base)
} }
await this.profilesService.newProfile(result) profile.id = `${profile.type}:custom:${slugify(profile.name)}:${uuidv4()}`
this.config.store.profiles = [profile, ...this.config.store.profiles]
await this.config.save() await this.config.save()
} }
@@ -103,7 +100,7 @@ export class ProfilesSettingsTabComponent extends BaseComponent {
if (!result) { if (!result) {
return return
} }
await this.profilesService.writeProfile(result) Object.assign(profile, result)
await this.config.save() await this.config.save()
} }
@@ -124,6 +121,12 @@ export class ProfilesSettingsTabComponent extends BaseComponent {
return null return null
} }
// Fully replace the config
for (const k in profile) {
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
delete profile[k]
}
result.type = provider.id result.type = provider.id
return result return result
} }
@@ -141,79 +144,69 @@ export class ProfilesSettingsTabComponent extends BaseComponent {
cancelId: 1, cancelId: 1,
}, },
)).response === 0) { )).response === 0) {
await this.profilesService.deleteProfile(profile) this.profilesService.providerForProfile(profile)?.deleteProfile(
await this.config.save() this.profilesService.getConfigProxyForProfile(profile))
} this.config.store.profiles = this.config.store.profiles.filter(x => x !== profile)
} const profileHotkeyName = AppHotkeyProvider.getProfileHotkeyName(profile)
if (this.config.store.hotkeys.profile.hasOwnProperty(profileHotkeyName)) {
async newProfileGroup (): Promise<void> { const profileHotkeys = deepClone(this.config.store.hotkeys.profile)
const modal = this.ngbModal.open(PromptModalComponent)
modal.componentInstance.prompt = this.translate.instant('New group name')
const result = await modal.result.catch(() => null)
if (result?.value.trim()) {
await this.profilesService.newProfileGroup({ id: '', name: result.value })
await this.config.save()
}
}
async editProfileGroup (group: PartialProfileGroup<CollapsableProfileGroup>): Promise<void> {
const result = await this.showProfileGroupEditModal(group)
if (!result) {
return
}
await this.profilesService.writeProfileGroup(ProfilesSettingsTabComponent.collapsableIntoPartialProfileGroup(result))
await this.config.save()
}
async showProfileGroupEditModal (group: PartialProfileGroup<CollapsableProfileGroup>): Promise<PartialProfileGroup<CollapsableProfileGroup>|null> {
const modal = this.ngbModal.open(
EditProfileGroupModalComponent,
{ size: 'lg' },
)
modal.componentInstance.group = deepClone(group)
modal.componentInstance.providers = this.profileProviders
const result: EditProfileGroupModalComponentResult<CollapsableProfileGroup> | null = await modal.result.catch(() => null)
if (!result) {
return null
}
if (result.provider) {
return this.editProfileGroupDefaults(result.group, result.provider)
}
return result.group
}
private async editProfileGroupDefaults (group: PartialProfileGroup<CollapsableProfileGroup>, provider: ProfileProvider<Profile>): Promise<PartialProfileGroup<CollapsableProfileGroup>|null> {
const modal = this.ngbModal.open(
EditProfileModalComponent,
{ size: 'lg' },
)
const model = group.defaults?.[provider.id] ?? {}
model.type = provider.id
modal.componentInstance.profile = Object.assign({}, model)
modal.componentInstance.profileProvider = provider
modal.componentInstance.defaultsMode = 'group'
const result = await modal.result.catch(() => null)
if (result) {
// Fully replace the config
for (const k in model) {
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete // eslint-disable-next-line @typescript-eslint/no-dynamic-delete
delete model[k] delete profileHotkeys[profileHotkeyName]
this.config.store.hotkeys.profile = profileHotkeys
} }
Object.assign(model, result) await this.config.save()
if (!group.defaults) {
group.defaults = {}
} }
group.defaults[provider.id] = model
}
return this.showProfileGroupEditModal(group)
} }
async deleteProfileGroup (group: PartialProfileGroup<ProfileGroup>): Promise<void> { refresh (): void {
this.profiles = this.config.store.profiles
this.profileGroups = []
const profileGroupCollapsed = JSON.parse(window.localStorage.profileGroupCollapsed ?? '{}')
for (const profile of this.profiles) {
// Group null, undefined and empty together
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
let group = this.profileGroups.find(x => x.name === (profile.group || ''))
if (!group) {
group = {
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
name: profile.group || '',
profiles: [],
editable: true,
collapsed: profileGroupCollapsed[profile.group ?? ''] ?? false,
}
this.profileGroups.push(group)
}
group.profiles.push(profile)
}
this.profileGroups.sort((a, b) => a.name?.localeCompare(b.name ?? '') ?? -1)
const builtIn = {
name: this.translate.instant('Built-in'),
profiles: this.builtinProfiles,
editable: false,
collapsed: false,
}
builtIn.collapsed = profileGroupCollapsed[builtIn.name ?? ''] ?? false
this.profileGroups.push(builtIn)
}
async editGroup (group: ProfileGroup): Promise<void> {
const modal = this.ngbModal.open(PromptModalComponent)
modal.componentInstance.prompt = this.translate.instant('New name')
modal.componentInstance.value = group.name
const result = await modal.result
if (result) {
for (const profile of this.profiles.filter(x => x.group === group.name)) {
profile.group = result.value
}
this.config.store.profiles = this.profiles
await this.config.save()
}
}
async deleteGroup (group: ProfileGroup): Promise<void> {
if ((await this.platform.showMessageBox( if ((await this.platform.showMessageBox(
{ {
type: 'warning', type: 'warning',
@@ -226,8 +219,7 @@ export class ProfilesSettingsTabComponent extends BaseComponent {
cancelId: 1, cancelId: 1,
}, },
)).response === 0) { )).response === 0) {
let deleteProfiles = false if ((await this.platform.showMessageBox(
if ((group.profiles?.length ?? 0) > 0 && (await this.platform.showMessageBox(
{ {
type: 'warning', type: 'warning',
message: this.translate.instant('Delete the group\'s profiles?'), message: this.translate.instant('Delete the group\'s profiles?'),
@@ -238,26 +230,19 @@ export class ProfilesSettingsTabComponent extends BaseComponent {
defaultId: 0, defaultId: 0,
cancelId: 0, cancelId: 0,
}, },
)).response !== 0) { )).response === 0) {
deleteProfiles = true for (const profile of this.profiles.filter(x => x.group === group.name)) {
delete profile.group
}
} else {
this.config.store.profiles = this.config.store.profiles.filter(x => x.group !== group.name)
} }
await this.profilesService.deleteProfileGroup(group, { deleteProfiles })
await this.config.save() await this.config.save()
} }
} }
async refreshProfileGroups (): Promise<void> { isGroupVisible (group: ProfileGroup): boolean {
const profileGroupCollapsed = JSON.parse(window.localStorage.profileGroupCollapsed ?? '{}') return !this.filter || group.profiles.some(x => this.isProfileVisible(x))
const groups = await this.profilesService.getProfileGroups({ includeNonUserGroup: true, includeProfiles: true })
groups.sort((a, b) => a.name.localeCompare(b.name))
groups.sort((a, b) => (a.id === 'built-in' || !a.editable ? 1 : 0) - (b.id === 'built-in' || !b.editable ? 1 : 0))
groups.sort((a, b) => (a.id === 'ungrouped' ? 0 : 1) - (b.id === 'ungrouped' ? 0 : 1))
this.profileGroups = groups.map(g => ProfilesSettingsTabComponent.intoPartialCollapsableProfileGroup(g, profileGroupCollapsed[g.id] ?? false))
}
isGroupVisible (group: PartialProfileGroup<ProfileGroup>): boolean {
return !this.filter || (group.profiles ?? []).some(x => this.isProfileVisible(x))
} }
isProfileVisible (profile: PartialProfile<Profile>): boolean { isProfileVisible (profile: PartialProfile<Profile>): boolean {
@@ -285,12 +270,11 @@ export class ProfilesSettingsTabComponent extends BaseComponent {
}[this.profilesService.providerForProfile(profile)?.id ?? ''] ?? 'warning' }[this.profilesService.providerForProfile(profile)?.id ?? ''] ?? 'warning'
} }
toggleGroupCollapse (group: PartialProfileGroup<CollapsableProfileGroup>): void { toggleGroupCollapse (group: ProfileGroup): void {
if (group.profiles?.length === 0) {
return
}
group.collapsed = !group.collapsed group.collapsed = !group.collapsed
this.saveProfileGroupCollapse(group) const profileGroupCollapsed = JSON.parse(window.localStorage.profileGroupCollapsed ?? '{}')
profileGroupCollapsed[group.name ?? ''] = group.collapsed
window.localStorage.profileGroupCollapsed = JSON.stringify(profileGroupCollapsed)
} }
async editDefaults (provider: ProfileProvider<Profile>): Promise<void> { async editDefaults (provider: ProfileProvider<Profile>): Promise<void> {
@@ -298,41 +282,22 @@ export class ProfilesSettingsTabComponent extends BaseComponent {
EditProfileModalComponent, EditProfileModalComponent,
{ size: 'lg' }, { size: 'lg' },
) )
const model = this.profilesService.getProviderDefaults(provider) const model = this.config.store.profileDefaults[provider.id] ?? {}
model.type = provider.id model.type = provider.id
modal.componentInstance.profile = Object.assign({}, model) modal.componentInstance.profile = Object.assign({}, model)
modal.componentInstance.profileProvider = provider modal.componentInstance.profileProvider = provider
modal.componentInstance.defaultsMode = 'enabled' modal.componentInstance.defaultsMode = true
const result = await modal.result.catch(() => null) const result = await modal.result
if (result) {
// Fully replace the config // Fully replace the config
for (const k in model) { for (const k in model) {
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete // eslint-disable-next-line @typescript-eslint/no-dynamic-delete
delete model[k] delete model[k]
} }
Object.assign(model, result) Object.assign(model, result)
this.profilesService.setProviderDefaults(provider, model) this.config.store.profileDefaults[provider.id] = model
await this.config.save() await this.config.save()
} }
}
async deleteDefaults (provider: ProfileProvider<Profile>): Promise<void> {
if ((await this.platform.showMessageBox(
{
type: 'warning',
message: this.translate.instant('Restore settings to defaults ?'),
buttons: [
this.translate.instant('Delete'),
this.translate.instant('Keep'),
],
defaultId: 1,
cancelId: 1,
},
)).response === 0) {
this.profilesService.setProviderDefaults(provider, {})
await this.config.save()
}
}
blacklistProfile (profile: PartialProfile<Profile>): void { blacklistProfile (profile: PartialProfile<Profile>): void {
this.config.store.profileBlacklist = [...this.config.store.profileBlacklist, profile.id] this.config.store.profileBlacklist = [...this.config.store.profileBlacklist, profile.id]
@@ -349,29 +314,6 @@ export class ProfilesSettingsTabComponent extends BaseComponent {
} }
getQuickConnectProviders (): ProfileProvider<Profile>[] { getQuickConnectProviders (): ProfileProvider<Profile>[] {
return this.profileProviders.filter(x => x instanceof QuickConnectProfileProvider) return this.profileProviders.filter(x => x.supportsQuickConnect)
}
/**
* Save ProfileGroup collapse state in localStorage
*/
private saveProfileGroupCollapse (group: PartialProfileGroup<CollapsableProfileGroup>): void {
const profileGroupCollapsed = JSON.parse(window.localStorage.profileGroupCollapsed ?? '{}')
profileGroupCollapsed[group.id] = group.collapsed
window.localStorage.profileGroupCollapsed = JSON.stringify(profileGroupCollapsed)
}
private static collapsableIntoPartialProfileGroup (group: PartialProfileGroup<CollapsableProfileGroup>): PartialProfileGroup<ProfileGroup> {
const g: any = { ...group }
delete g.collapsed
return g
}
private static intoPartialCollapsableProfileGroup (group: PartialProfileGroup<ProfileGroup>, collapsed: boolean): PartialProfileGroup<CollapsableProfileGroup> {
const collapsableGroup = {
...group,
collapsed,
}
return collapsableGroup
} }
} }

View File

@@ -1,15 +0,0 @@
h4.modal-header.m-0.pb-0 {{title}}
.modal-body
.input-group.w-100
input.form-control(
type='text',
[(ngModel)]='secret.value',
disabled
)
button.btn.btn-secondary(
(click)='copySecret()'
)
i.fas.fa-copy
.modal-footer
button.btn.btn-primary((click)='close()', translate) Close

View File

@@ -1,27 +0,0 @@
import { Component, Input } from '@angular/core'
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'
import { NotificationsService, VaultFileSecret } from 'tabby-core'
/** @hidden */
@Component({
templateUrl: './showSecretModal.component.pug',
})
export class ShowSecretModalComponent {
@Input() title: string
@Input() secret: VaultFileSecret
constructor (
public modalInstance: NgbActiveModal,
private notifications: NotificationsService,
) { }
close (): void {
this.modalInstance.dismiss()
}
copySecret (): void {
navigator.clipboard.writeText(this.secret.value)
// Show a notification
this.notifications.info('Copied to clipboard')
}
}

View File

@@ -32,9 +32,6 @@ div(*ngIf='vault.isEnabled()')
button.btn.btn-link(ngbDropdownToggle) button.btn.btn-link(ngbDropdownToggle)
i.fas.fa-ellipsis-v i.fas.fa-ellipsis-v
div(ngbDropdownMenu) div(ngbDropdownMenu)
button(ngbDropdownItem, (click)='showSecret(secret)')
i.fas.fa-fw.fa-eye
span(translate) Show
button( button(
ngbDropdownItem, ngbDropdownItem,
*ngIf='secret.type === VAULT_SECRET_TYPE_FILE', *ngIf='secret.type === VAULT_SECRET_TYPE_FILE',

View File

@@ -3,7 +3,6 @@ import { Component, HostBinding } from '@angular/core'
import { NgbModal } from '@ng-bootstrap/ng-bootstrap' import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
import { BaseComponent, VaultService, VaultSecret, Vault, PlatformService, ConfigService, VAULT_SECRET_TYPE_FILE, PromptModalComponent, VaultFileSecret, TranslateService } from 'tabby-core' import { BaseComponent, VaultService, VaultSecret, Vault, PlatformService, ConfigService, VAULT_SECRET_TYPE_FILE, PromptModalComponent, VaultFileSecret, TranslateService } from 'tabby-core'
import { SetVaultPassphraseModalComponent } from './setVaultPassphraseModal.component' import { SetVaultPassphraseModalComponent } from './setVaultPassphraseModal.component'
import { ShowSecretModalComponent } from './showSecretModal.component'
/** @hidden */ /** @hidden */
@@ -36,12 +35,10 @@ export class VaultSettingsTabComponent extends BaseComponent {
async enableVault () { async enableVault () {
const modal = this.ngbModal.open(SetVaultPassphraseModalComponent) const modal = this.ngbModal.open(SetVaultPassphraseModalComponent)
const newPassphrase = await modal.result.catch(() => null) const newPassphrase = await modal.result
if (newPassphrase) {
await this.vault.setEnabled(true, newPassphrase) await this.vault.setEnabled(true, newPassphrase)
this.vaultContents = await this.vault.load(newPassphrase) this.vaultContents = await this.vault.load(newPassphrase)
} }
}
async disableVault () { async disableVault () {
if ((await this.platform.showMessageBox( if ((await this.platform.showMessageBox(
@@ -68,11 +65,9 @@ export class VaultSettingsTabComponent extends BaseComponent {
return return
} }
const modal = this.ngbModal.open(SetVaultPassphraseModalComponent) const modal = this.ngbModal.open(SetVaultPassphraseModalComponent)
const newPassphrase = await modal.result.catch(() => null) const newPassphrase = await modal.result
if (newPassphrase) {
this.vault.save(this.vaultContents, newPassphrase) this.vault.save(this.vaultContents, newPassphrase)
} }
}
async toggleConfigEncrypted () { async toggleConfigEncrypted () {
this.config.store.encrypted = !this.config.store.encrypted this.config.store.encrypted = !this.config.store.encrypted
@@ -98,16 +93,6 @@ export class VaultSettingsTabComponent extends BaseComponent {
return this.translate.instant('Unknown secret of type {type} for {key}', { type: secret.type, key: JSON.stringify(secret.key) }) return this.translate.instant('Unknown secret of type {type} for {key}', { type: secret.type, key: JSON.stringify(secret.key) })
} }
showSecret (secret: VaultSecret) {
if (!this.vaultContents) {
return
}
const modal = this.ngbModal.open(ShowSecretModalComponent)
modal.componentInstance.title = this.getSecretLabel(secret)
modal.componentInstance.secret = secret
}
removeSecret (secret: VaultSecret) { removeSecret (secret: VaultSecret) {
if (!this.vaultContents) { if (!this.vaultContents) {
return return
@@ -133,7 +118,7 @@ export class VaultSettingsTabComponent extends BaseComponent {
modal.componentInstance.prompt = this.translate.instant('New name') modal.componentInstance.prompt = this.translate.instant('New name')
modal.componentInstance.value = secret.key.description modal.componentInstance.value = secret.key.description
const description = (await modal.result.catch(() => null))?.value const description = (await modal.result)?.value
if (!description) { if (!description) {
return return
} }

View File

@@ -4,8 +4,8 @@ import { ConfigProvider, Platform } from 'tabby-core'
export class SettingsConfigProvider extends ConfigProvider { export class SettingsConfigProvider extends ConfigProvider {
defaults = { defaults = {
configSync: { configSync: {
host: null, host: 'https://api.tabby.sh',
token: null, token: '',
configID: null, configID: null,
auto: false, auto: false,
parts: { parts: {
@@ -20,7 +20,6 @@ export class SettingsConfigProvider extends ConfigProvider {
}, },
}, },
} }
platformDefaults = { platformDefaults = {
[Platform.macOS]: { [Platform.macOS]: {
hotkeys: { hotkeys: {

View File

@@ -7,7 +7,6 @@ import { InfiniteScrollModule } from 'ngx-infinite-scroll'
import TabbyCorePlugin, { ToolbarButtonProvider, HotkeyProvider, ConfigProvider, HotkeysService, AppService } from 'tabby-core' import TabbyCorePlugin, { ToolbarButtonProvider, HotkeyProvider, ConfigProvider, HotkeysService, AppService } from 'tabby-core'
import { EditProfileModalComponent } from './components/editProfileModal.component' import { EditProfileModalComponent } from './components/editProfileModal.component'
import { EditProfileGroupModalComponent } from './components/editProfileGroupModal.component'
import { HotkeyInputModalComponent } from './components/hotkeyInputModal.component' import { HotkeyInputModalComponent } from './components/hotkeyInputModal.component'
import { HotkeySettingsTabComponent } from './components/hotkeySettingsTab.component' import { HotkeySettingsTabComponent } from './components/hotkeySettingsTab.component'
import { MultiHotkeyInputComponent } from './components/multiHotkeyInput.component' import { MultiHotkeyInputComponent } from './components/multiHotkeyInput.component'
@@ -19,7 +18,6 @@ import { SetVaultPassphraseModalComponent } from './components/setVaultPassphras
import { ProfilesSettingsTabComponent } from './components/profilesSettingsTab.component' import { ProfilesSettingsTabComponent } from './components/profilesSettingsTab.component'
import { ReleaseNotesComponent } from './components/releaseNotesTab.component' import { ReleaseNotesComponent } from './components/releaseNotesTab.component'
import { ConfigSyncSettingsTabComponent } from './components/configSyncSettingsTab.component' import { ConfigSyncSettingsTabComponent } from './components/configSyncSettingsTab.component'
import { ShowSecretModalComponent } from './components/showSecretModal.component'
import { ConfigSyncService } from './services/configSync.service' import { ConfigSyncService } from './services/configSync.service'
@@ -50,7 +48,6 @@ import { HotkeySettingsTabProvider, WindowSettingsTabProvider, VaultSettingsTabP
], ],
declarations: [ declarations: [
EditProfileModalComponent, EditProfileModalComponent,
EditProfileGroupModalComponent,
HotkeyInputModalComponent, HotkeyInputModalComponent,
HotkeySettingsTabComponent, HotkeySettingsTabComponent,
MultiHotkeyInputComponent, MultiHotkeyInputComponent,
@@ -62,7 +59,6 @@ import { HotkeySettingsTabProvider, WindowSettingsTabProvider, VaultSettingsTabP
WindowSettingsTabComponent, WindowSettingsTabComponent,
ConfigSyncSettingsTabComponent, ConfigSyncSettingsTabComponent,
ReleaseNotesComponent, ReleaseNotesComponent,
ShowSecretModalComponent,
], ],
}) })
export default class SettingsModule { export default class SettingsModule {

View File

@@ -25,7 +25,6 @@
"@types/node": "20.3.1", "@types/node": "20.3.1",
"@types/ssh2": "^0.5.46", "@types/ssh2": "^0.5.46",
"ansi-colors": "^4.1.1", "ansi-colors": "^4.1.1",
"diffie-hellman": "^5.0.3",
"sshpk": "Eugeny/node-sshpk#c2b71d1243714d2daf0988f84c3323d180817136", "sshpk": "Eugeny/node-sshpk#c2b71d1243714d2daf0988f84c3323d180817136",
"strip-ansi": "^7.0.0" "strip-ansi": "^7.0.0"
}, },

View File

@@ -1,4 +1,4 @@
import { ConnectableTerminalProfile, InputProcessingOptions, LoginScriptsOptions } from 'tabby-terminal' import { BaseTerminalProfile, InputProcessingOptions, LoginScriptsOptions } from 'tabby-terminal'
export enum SSHAlgorithmType { export enum SSHAlgorithmType {
HMAC = 'hmac', HMAC = 'hmac',
@@ -7,7 +7,7 @@ export enum SSHAlgorithmType {
HOSTKEY = 'serverHostKey', HOSTKEY = 'serverHostKey',
} }
export interface SSHProfile extends ConnectableTerminalProfile { export interface SSHProfile extends BaseTerminalProfile {
options: SSHProfileOptions options: SSHProfileOptions
} }

View File

@@ -18,7 +18,6 @@ export class SFTPCreateDirectoryModalComponent extends BaseComponent {
create (): void { create (): void {
this.modalInstance.close(this.directoryName) this.modalInstance.close(this.directoryName)
} }
cancel (): void { cancel (): void {
this.modalInstance.close('') this.modalInstance.close('')
} }

View File

@@ -113,8 +113,8 @@ export class SFTPPanelComponent {
async openCreateDirectoryModal (): Promise<void> { async openCreateDirectoryModal (): Promise<void> {
const modal = this.ngbModal.open(SFTPCreateDirectoryModalComponent) const modal = this.ngbModal.open(SFTPCreateDirectoryModalComponent)
const directoryName = await modal.result.catch(() => null) const directoryName = await modal.result
if (directoryName?.trim()) { if (directoryName !== '') {
this.sftp.mkdir(path.join(this.path, directoryName)).then(() => { this.sftp.mkdir(path.join(this.path, directoryName)).then(() => {
this.notifications.notice('The directory was created successfully') this.notifications.notice('The directory was created successfully')
this.navigate(path.join(this.path, directoryName)) this.navigate(path.join(this.path, directoryName))

View File

@@ -160,12 +160,10 @@ ul.nav-tabs(ngbNav, #nav='ngbNav')
type='radio', type='radio',
name='auth', name='auth',
[(ngModel)]='profile.options.auth', [(ngModel)]='profile.options.auth',
id='auth"keyboardInteractive"', id='auth"keyboardInteractive"'
[value]='"keyboardInteractive"' [value]='"keyboardInteractive"'
) )
label.btn.btn-secondary( label.btn.btn-secondary(ngbButtonLabel)
for='auth"keyboardInteractive"'
)
i.far.fa-keyboard i.far.fa-keyboard
.m-0(translate) Interactive .m-0(translate) Interactive

View File

@@ -75,7 +75,7 @@ export class SSHProfileSettingsComponent {
modal.componentInstance.prompt = `Password for ${this.profile.options.user}@${this.profile.options.host}` modal.componentInstance.prompt = `Password for ${this.profile.options.user}@${this.profile.options.host}`
modal.componentInstance.password = true modal.componentInstance.password = true
try { try {
const result = await modal.result.catch(() => null) const result = await modal.result
if (result?.value) { if (result?.value) {
this.passwordStorage.savePassword(this.profile, result.value) this.passwordStorage.savePassword(this.profile, result.value)
this.hasSavedPassword = true this.hasSavedPassword = true
@@ -89,14 +89,12 @@ export class SSHProfileSettingsComponent {
} }
async addPrivateKey () { async addPrivateKey () {
const ref = await this.fileProviders.selectAndStoreFile(`private key for ${this.profile.name}`).catch(() => null) const ref = await this.fileProviders.selectAndStoreFile(`private key for ${this.profile.name}`)
if (ref) {
this.profile.options.privateKeys = [ this.profile.options.privateKeys = [
...this.profile.options.privateKeys!, ...this.profile.options.privateKeys!,
ref, ref,
] ]
} }
}
removePrivateKey (path: string) { removePrivateKey (path: string) {
this.profile.options.privateKeys = this.profile.options.privateKeys?.filter(x => x !== path) this.profile.options.privateKeys = this.profile.options.privateKeys?.filter(x => x !== path)

View File

@@ -61,4 +61,12 @@ h3 SSH
(ngModelChange)='config.save()' (ngModelChange)='config.save()'
) )
.form-line
.header
.title(translate) Clear terminal after connection
toggle(
[(ngModel)]='config.store.ssh.clearServiceMessagesOnConnect',
(ngModelChange)='config.save()',
)
.alert.alert-info(translate) SSH connection management is now done through the "Profiles & connections" tab .alert.alert-info(translate) SSH connection management is now done through the "Profiles & connections" tab

View File

@@ -83,7 +83,7 @@ export class SSHTabComponent extends ConnectableTerminalTabComponent<SSHProfile>
const jumpSession = await this.setupOneSession( const jumpSession = await this.setupOneSession(
this.injector, this.injector,
this.profilesService.getConfigProxyForProfile<SSHProfile>(jumpConnection), this.profilesService.getConfigProxyForProfile(jumpConnection),
) )
jumpSession.ref() jumpSession.ref()
@@ -163,6 +163,10 @@ export class SSHTabComponent extends ConnectableTerminalTabComponent<SSHProfile>
await session.start() await session.start()
if (this.config.store.ssh.clearServiceMessagesOnConnect) {
this.frontend?.clear()
}
this.session?.resize(this.size.columns, this.size.rows) this.session?.resize(this.size.columns, this.size.rows)
} }

View File

@@ -11,6 +11,7 @@ export class SSHConfigProvider extends ConfigProvider {
x11Display: null, x11Display: null,
knownHosts: [], knownHosts: [],
verifyHostKeys: true, verifyHostKeys: true,
clearServiceMessagesOnConnect: true,
}, },
hotkeys: { hotkeys: {
'restart-ssh-session': [], 'restart-ssh-session': [],

View File

@@ -1,5 +1,3 @@
import './polyfills'
import { NgModule } from '@angular/core' import { NgModule } from '@angular/core'
import { CommonModule } from '@angular/common' import { CommonModule } from '@angular/common'
import { FormsModule } from '@angular/forms' import { FormsModule } from '@angular/forms'

Some files were not shown because too many files have changed in this diff Show More