mirror of
https://github.com/Eugeny/tabby.git
synced 2025-08-21 16:51:52 +00:00
Compare commits
86 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
467684d9ab | ||
![]() |
5069070040 | ||
![]() |
ecf5297bc3 | ||
![]() |
78bd90ac55 | ||
![]() |
712589eb93 | ||
![]() |
f103e71285 | ||
![]() |
0cf883cc4a | ||
![]() |
2b0ad0d558 | ||
![]() |
67bacb9dd3 | ||
![]() |
d0a597634d | ||
![]() |
322014c409 | ||
![]() |
c751a8725b | ||
![]() |
5417efe558 | ||
![]() |
bf356fcd19 | ||
![]() |
10ee66b9dd | ||
![]() |
763da0d80c | ||
![]() |
8d46bb2181 | ||
![]() |
fe936c7726 | ||
![]() |
2f3e32990a | ||
![]() |
22344f8d54 | ||
![]() |
f6d37a39f4 | ||
![]() |
0e4c60ad4b | ||
![]() |
e8c2171d8f | ||
![]() |
f7a5be2c67 | ||
![]() |
39fa0424a6 | ||
![]() |
bcb1b6a13b | ||
![]() |
a19f35ac44 | ||
![]() |
ea92f1a700 | ||
![]() |
b5701cf9f9 | ||
![]() |
4742530cf3 | ||
![]() |
a8d78ce185 | ||
![]() |
bba1eaccbe | ||
![]() |
cd6d05aa69 | ||
![]() |
412403c72a | ||
![]() |
93ae907dd1 | ||
![]() |
ce24b9cc52 | ||
![]() |
dc68372d76 | ||
![]() |
e0fe125cf2 | ||
![]() |
e594fcd0e7 | ||
![]() |
0219da4d85 | ||
![]() |
5e06b2248b | ||
![]() |
cdc3623986 | ||
![]() |
6d016002c0 | ||
![]() |
f3569f5d2d | ||
![]() |
4125582ef2 | ||
![]() |
c6331c9b1c | ||
![]() |
aaab475e5f | ||
![]() |
e6bf76c616 | ||
![]() |
e36bad2553 | ||
![]() |
154cc29333 | ||
![]() |
1b0402c2cf | ||
![]() |
15073cbc81 | ||
![]() |
3365b143d8 | ||
![]() |
4d9cc91e91 | ||
![]() |
946f4292ef | ||
![]() |
eb12b1ae60 | ||
![]() |
4765c97d31 | ||
![]() |
3fb32e1a97 | ||
![]() |
9ec1a0d253 | ||
![]() |
fef19615bb | ||
![]() |
4d237baf33 | ||
![]() |
03e654b5a0 | ||
![]() |
ef815eaa40 | ||
![]() |
4771a38747 | ||
![]() |
ce016793d4 | ||
![]() |
3a854f04e1 | ||
![]() |
b5658d61d9 | ||
![]() |
02750d8581 | ||
![]() |
077a3e6bba | ||
![]() |
5454be032a | ||
![]() |
8a0b4f82db | ||
![]() |
74fd1aeea5 | ||
![]() |
aac230e362 | ||
![]() |
ae82ed4a47 | ||
![]() |
9d1b0e9861 | ||
![]() |
8cb4e9f27d | ||
![]() |
c8c00a2c9b | ||
![]() |
bacb475896 | ||
![]() |
c8faa67083 | ||
![]() |
b6c0e3cdfb | ||
![]() |
323581d513 | ||
![]() |
21b81f476c | ||
![]() |
2283a5dad9 | ||
![]() |
d7565e497d | ||
![]() |
7b4e99fc5f | ||
![]() |
035a6f8da8 |
@@ -334,6 +334,15 @@
|
|||||||
"contributions": [
|
"contributions": [
|
||||||
"code"
|
"code"
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "frauhottelmann",
|
||||||
|
"name": "frauhottelmann",
|
||||||
|
"avatar_url": "https://avatars2.githubusercontent.com/u/902705?v=4",
|
||||||
|
"profile": "https://github.com/frauhottelmann",
|
||||||
|
"contributions": [
|
||||||
|
"code"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"contributorsPerLine": 7,
|
"contributorsPerLine": 7,
|
||||||
|
@@ -29,7 +29,6 @@ rules:
|
|||||||
'@typescript-eslint/no-magic-numbers': off
|
'@typescript-eslint/no-magic-numbers': off
|
||||||
'@typescript-eslint/member-delimiter-style': off
|
'@typescript-eslint/member-delimiter-style': off
|
||||||
'@typescript-eslint/promise-function-async': off
|
'@typescript-eslint/promise-function-async': off
|
||||||
'@typescript-eslint/no-unnecessary-type-assertion': off
|
|
||||||
'@typescript-eslint/require-array-sort-compare': off
|
'@typescript-eslint/require-array-sort-compare': off
|
||||||
'@typescript-eslint/no-floating-promises': off
|
'@typescript-eslint/no-floating-promises': off
|
||||||
'@typescript-eslint/prefer-readonly': off
|
'@typescript-eslint/prefer-readonly': off
|
||||||
@@ -95,25 +94,22 @@ rules:
|
|||||||
- error
|
- error
|
||||||
- single
|
- single
|
||||||
- allowTemplateLiterals: true
|
- allowTemplateLiterals: true
|
||||||
|
'@typescript-eslint/no-confusing-void-expression': off
|
||||||
'@typescript-eslint/no-non-null-assertion': off
|
'@typescript-eslint/no-non-null-assertion': off
|
||||||
'@typescript-eslint/no-unnecessary-condition': off
|
'@typescript-eslint/no-unnecessary-condition':
|
||||||
'@typescript-eslint/no-untyped-public-signature': off # bugs out on constructors
|
- error
|
||||||
|
- allowConstantLoopConditions: true
|
||||||
'@typescript-eslint/restrict-template-expressions': off
|
'@typescript-eslint/restrict-template-expressions': off
|
||||||
'@typescript-eslint/no-dynamic-delete': off
|
|
||||||
'@typescript-eslint/prefer-nullish-coalescing': off
|
|
||||||
'@typescript-eslint/prefer-readonly-parameter-types': off
|
'@typescript-eslint/prefer-readonly-parameter-types': off
|
||||||
'@typescript-eslint/no-unsafe-member-access': off
|
'@typescript-eslint/no-unsafe-member-access': off
|
||||||
'@typescript-eslint/no-unsafe-call': off
|
'@typescript-eslint/no-unsafe-call': off
|
||||||
'@typescript-eslint/no-unsafe-return': off
|
'@typescript-eslint/no-unsafe-return': off
|
||||||
'@typescript-eslint/no-base-to-string': off # broken in typescript-eslint
|
|
||||||
'@typescript-eslint/no-unsafe-assignment': off
|
'@typescript-eslint/no-unsafe-assignment': off
|
||||||
'@typescript-eslint/naming-convention': off
|
'@typescript-eslint/naming-convention': off
|
||||||
'@typescript-eslint/lines-between-class-members':
|
'@typescript-eslint/lines-between-class-members':
|
||||||
- error
|
- error
|
||||||
- exceptAfterSingleLine: true
|
- exceptAfterSingleLine: true
|
||||||
'@typescript-eslint/dot-notation': off
|
'@typescript-eslint/dot-notation': off
|
||||||
'@typescript-eslint/no-confusing-void-expression': off
|
|
||||||
'@typescript-eslint/no-implicit-any-catch': off
|
'@typescript-eslint/no-implicit-any-catch': off
|
||||||
'@typescript-eslint/member-ordering': off
|
'@typescript-eslint/member-ordering': off
|
||||||
'@typescript-eslint/no-var-requires': off
|
'@typescript-eslint/no-var-requires': off
|
||||||
'@typescript-eslint/no-shadow': off
|
|
||||||
|
10
.github/workflows/linux.yml
vendored
10
.github/workflows/linux.yml
vendored
@@ -36,6 +36,16 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
DEBUG: electron-builder,electron-builder:*
|
DEBUG: electron-builder,electron-builder:*
|
||||||
GH_TOKEN: ${{ secrets.GH_TOKEN }}
|
GH_TOKEN: ${{ secrets.GH_TOKEN }}
|
||||||
|
USE_HARD_LINKS: false
|
||||||
|
|
||||||
|
- name: Upload symbols
|
||||||
|
run: |
|
||||||
|
sudo npm install -g @sentry/cli --unsafe-perm
|
||||||
|
./scripts/sentry-upload.js
|
||||||
|
env:
|
||||||
|
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
|
||||||
|
SENTRY_ORG: ${{ secrets.SENTRY_ORG }}
|
||||||
|
SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }}
|
||||||
|
|
||||||
- name: Package artifacts
|
- name: Package artifacts
|
||||||
run: |
|
run: |
|
||||||
|
15
.github/workflows/macos.yml
vendored
15
.github/workflows/macos.yml
vendored
@@ -7,7 +7,9 @@ jobs:
|
|||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
- arch: x86_64
|
- arch: x86_64
|
||||||
|
electron_setup_cmd: 'true'
|
||||||
- arch: arm64
|
- arch: arm64
|
||||||
|
electron_setup_cmd: 'yarn add -D electron@11.1.1'
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
@@ -27,6 +29,9 @@ jobs:
|
|||||||
rm app/node_modules/.yarn-integrity
|
rm app/node_modules/.yarn-integrity
|
||||||
yarn
|
yarn
|
||||||
|
|
||||||
|
- name: Upgrade Electron for ARM builds
|
||||||
|
run: ${{ matrix.electron_setup_cmd }}
|
||||||
|
|
||||||
- name: Build native deps
|
- name: Build native deps
|
||||||
run: scripts/build-native.js
|
run: scripts/build-native.js
|
||||||
env:
|
env:
|
||||||
@@ -52,6 +57,7 @@ jobs:
|
|||||||
CSC_KEY_PASSWORD: ${{ secrets.CSC_KEY_PASSWORD }}
|
CSC_KEY_PASSWORD: ${{ secrets.CSC_KEY_PASSWORD }}
|
||||||
APPSTORE_USERNAME: ${{ secrets.APPSTORE_USERNAME }}
|
APPSTORE_USERNAME: ${{ secrets.APPSTORE_USERNAME }}
|
||||||
APPSTORE_PASSWORD: ${{ secrets.APPSTORE_PASSWORD }}
|
APPSTORE_PASSWORD: ${{ secrets.APPSTORE_PASSWORD }}
|
||||||
|
USE_HARD_LINKS: false
|
||||||
# DEBUG: electron-builder,electron-builder:*
|
# DEBUG: electron-builder,electron-builder:*
|
||||||
|
|
||||||
- name: Build packages without signing
|
- name: Build packages without signing
|
||||||
@@ -61,6 +67,15 @@ jobs:
|
|||||||
ARCH: ${{matrix.arch}}
|
ARCH: ${{matrix.arch}}
|
||||||
# DEBUG: electron-builder,electron-builder:*
|
# DEBUG: electron-builder,electron-builder:*
|
||||||
|
|
||||||
|
- name: Upload symbols
|
||||||
|
run: |
|
||||||
|
sudo npm install -g @sentry/cli --unsafe-perm
|
||||||
|
./scripts/sentry-upload.js
|
||||||
|
env:
|
||||||
|
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
|
||||||
|
SENTRY_ORG: ${{ secrets.SENTRY_ORG }}
|
||||||
|
SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }}
|
||||||
|
|
||||||
- name: Package artifacts
|
- name: Package artifacts
|
||||||
run: |
|
run: |
|
||||||
mkdir artifact-pkg
|
mkdir artifact-pkg
|
||||||
|
11
.github/workflows/windows.yml
vendored
11
.github/workflows/windows.yml
vendored
@@ -11,7 +11,7 @@ jobs:
|
|||||||
- name: Installing Node
|
- name: Installing Node
|
||||||
uses: actions/setup-node@v1
|
uses: actions/setup-node@v1
|
||||||
with:
|
with:
|
||||||
node-version: 15
|
node-version: 14
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
shell: powershell
|
shell: powershell
|
||||||
@@ -34,6 +34,15 @@ jobs:
|
|||||||
run: node scripts/build-windows.js
|
run: node scripts/build-windows.js
|
||||||
if: github.repository != 'Eugeny/terminus' || github.event_name != 'push'
|
if: github.repository != 'Eugeny/terminus' || github.event_name != 'push'
|
||||||
|
|
||||||
|
- name: Upload symbols
|
||||||
|
run: |
|
||||||
|
npm install @sentry/cli
|
||||||
|
node scripts/sentry-upload.js
|
||||||
|
env:
|
||||||
|
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
|
||||||
|
SENTRY_ORG: ${{ secrets.SENTRY_ORG }}
|
||||||
|
SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }}
|
||||||
|
|
||||||
- name: Package artifacts
|
- name: Package artifacts
|
||||||
run: |
|
run: |
|
||||||
mkdir artifact-setup
|
mkdir artifact-setup
|
||||||
|
80
README.md
80
README.md
@@ -2,11 +2,11 @@
|
|||||||
|
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<a href="https://raw.githubusercontent.com/Eugeny/terminus/master/LICENSE"><img alt="GitHub" src="https://img.shields.io/github/license/eugeny/terminus.svg?label=License&style=flat-square"></a> <a href="https://ci.appveyor.com/project/Eugeny/terminus"><img alt="AppVeyor" src="https://img.shields.io/appveyor/ci/eugeny/terminus.svg?label=CI&logo=appveyor&logoColor=white&style=flat-square"></a>
|
<a href="https://raw.githubusercontent.com/Eugeny/terminus/master/LICENSE"><img alt="GitHub" src="https://img.shields.io/github/license/eugeny/terminus.svg?label=License&style=flat-square"></a> <a href="https://ci.appveyor.com/project/Eugeny/terminus"><img alt="AppVeyor" src="https://img.shields.io/appveyor/ci/eugeny/****terminus****.svg?label=CI&logo=appveyor&logoColor=white&style=flat-square"></a>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<a href="https://github.com/Eugeny/terminus/releases/latest"><img alt="GitHub All Releases" src="https://img.shields.io/github/downloads/eugeny/terminus/total.svg?label=DOWNLOAD&logo=github&style=for-the-badge"></a> <a href="https://ci.appveyor.com/project/Eugeny/terminus/build/artifacts"><img src="https://img.shields.io/badge/download-nightly%20build-magenta.svg?logo=appveyor&style=for-the-badge"/></a> <a href="https://gitter.im/terminus-terminal/community"><img alt="Gitter" src="https://img.shields.io/gitter/room/terminus/community.svg?color=blue&logo=gitter&style=for-the-badge"></a>
|
<a href="https://github.com/Eugeny/terminus/releases/latest"><img alt="GitHub All Releases" src="https://img.shields.io/github/downloads/eugeny/terminus/total.svg?label=RELEASE&logo=github&style=for-the-badge"></a> <a href="https://nightly.link/Eugeny/terminus/workflows/windows/master"><img src="https://shields.io/badge/-Nightly-blue?logo=windows&style=for-the-badge"/></a> <a href="https://nightly.link/Eugeny/terminus/workflows/macos/master"><img src="https://shields.io/badge/-Nightly-black?logo=apple&style=for-the-badge"/></a> <a href="https://nightly.link/Eugeny/terminus/workflows/linux/master"><img src="https://shields.io/badge/-Nightly-orange?logo=linux&style=for-the-badge"/></a> <a href="https://gitter.im/terminus-terminal/community"><img alt="Gitter" src="https://img.shields.io/gitter/room/terminus/community.svg?color=magenta&logo=gitter&style=for-the-badge"></a>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
----
|
----
|
||||||
@@ -74,57 +74,59 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
|
|||||||
<!-- markdownlint-disable -->
|
<!-- markdownlint-disable -->
|
||||||
<table>
|
<table>
|
||||||
<tr>
|
<tr>
|
||||||
<td align="center"><a href="http://www.russellmyers.com"><img src="https://avatars2.githubusercontent.com/u/184085?v=4" width="100px;" alt=""/><br /><sub><b>Russell Myers</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=mezner" title="Code">💻</a></td>
|
<td align="center"><a href="http://www.russellmyers.com"><img src="https://avatars2.githubusercontent.com/u/184085?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Russell Myers</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=mezner" title="Code">💻</a></td>
|
||||||
<td align="center"><a href="http://www.morwire.com"><img src="https://avatars1.githubusercontent.com/u/3991658?v=4" width="100px;" alt=""/><br /><sub><b>Austin Warren</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=ehwarren" title="Code">💻</a></td>
|
<td align="center"><a href="http://www.morwire.com"><img src="https://avatars1.githubusercontent.com/u/3991658?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Austin Warren</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=ehwarren" title="Code">💻</a></td>
|
||||||
<td align="center"><a href="https://github.com/Drachenkaetzchen"><img src="https://avatars1.githubusercontent.com/u/162974?v=4" width="100px;" alt=""/><br /><sub><b>Felicia Hummel</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=Drachenkaetzchen" title="Code">💻</a></td>
|
<td align="center"><a href="https://github.com/Drachenkaetzchen"><img src="https://avatars1.githubusercontent.com/u/162974?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Felicia Hummel</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=Drachenkaetzchen" title="Code">💻</a></td>
|
||||||
<td align="center"><a href="https://github.com/mikemaccana"><img src="https://avatars2.githubusercontent.com/u/172594?v=4" width="100px;" alt=""/><br /><sub><b>Mike MacCana</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=mikemaccana" title="Tests">⚠️</a> <a href="#design-mikemaccana" title="Design">🎨</a></td>
|
<td align="center"><a href="https://github.com/mikemaccana"><img src="https://avatars2.githubusercontent.com/u/172594?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Mike MacCana</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=mikemaccana" title="Tests">⚠️</a> <a href="#design-mikemaccana" title="Design">🎨</a></td>
|
||||||
<td align="center"><a href="https://github.com/yxuko"><img src="https://avatars1.githubusercontent.com/u/1786317?v=4" width="100px;" alt=""/><br /><sub><b>Yacine Kanzari</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=yxuko" title="Code">💻</a></td>
|
<td align="center"><a href="https://github.com/yxuko"><img src="https://avatars1.githubusercontent.com/u/1786317?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Yacine Kanzari</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=yxuko" title="Code">💻</a></td>
|
||||||
<td align="center"><a href="https://github.com/BBJip"><img src="https://avatars2.githubusercontent.com/u/32908927?v=4" width="100px;" alt=""/><br /><sub><b>BBJip</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=BBJip" title="Code">💻</a></td>
|
<td align="center"><a href="https://github.com/BBJip"><img src="https://avatars2.githubusercontent.com/u/32908927?v=4?s=100" width="100px;" alt=""/><br /><sub><b>BBJip</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=BBJip" title="Code">💻</a></td>
|
||||||
<td align="center"><a href="https://github.com/Futagirl"><img src="https://avatars2.githubusercontent.com/u/33533958?v=4" width="100px;" alt=""/><br /><sub><b>Futagirl</b></sub></a><br /><a href="#design-Futagirl" title="Design">🎨</a></td>
|
<td align="center"><a href="https://github.com/Futagirl"><img src="https://avatars2.githubusercontent.com/u/33533958?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Futagirl</b></sub></a><br /><a href="#design-Futagirl" title="Design">🎨</a></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td align="center"><a href="https://www.levrik.io"><img src="https://avatars3.githubusercontent.com/u/9491603?v=4" width="100px;" alt=""/><br /><sub><b>Levin Rickert</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=levrik" title="Code">💻</a></td>
|
<td align="center"><a href="https://www.levrik.io"><img src="https://avatars3.githubusercontent.com/u/9491603?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Levin Rickert</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=levrik" title="Code">💻</a></td>
|
||||||
<td align="center"><a href="https://kwonoj.github.io"><img src="https://avatars2.githubusercontent.com/u/1210596?v=4" width="100px;" alt=""/><br /><sub><b>OJ Kwon</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=kwonoj" title="Code">💻</a></td>
|
<td align="center"><a href="https://kwonoj.github.io"><img src="https://avatars2.githubusercontent.com/u/1210596?v=4?s=100" width="100px;" alt=""/><br /><sub><b>OJ Kwon</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=kwonoj" title="Code">💻</a></td>
|
||||||
<td align="center"><a href="https://github.com/Domain"><img src="https://avatars2.githubusercontent.com/u/903197?v=4" width="100px;" alt=""/><br /><sub><b>domain</b></sub></a><br /><a href="#plugin-Domain" title="Plugin/utility libraries">🔌</a> <a href="https://github.com/Eugeny/terminus/commits?author=Domain" title="Code">💻</a></td>
|
<td align="center"><a href="https://github.com/Domain"><img src="https://avatars2.githubusercontent.com/u/903197?v=4?s=100" width="100px;" alt=""/><br /><sub><b>domain</b></sub></a><br /><a href="#plugin-Domain" title="Plugin/utility libraries">🔌</a> <a href="https://github.com/Eugeny/terminus/commits?author=Domain" title="Code">💻</a></td>
|
||||||
<td align="center"><a href="http://www.jbrumond.me"><img src="https://avatars1.githubusercontent.com/u/195127?v=4" width="100px;" alt=""/><br /><sub><b>James Brumond</b></sub></a><br /><a href="#plugin-kbjr" title="Plugin/utility libraries">🔌</a></td>
|
<td align="center"><a href="http://www.jbrumond.me"><img src="https://avatars1.githubusercontent.com/u/195127?v=4?s=100" width="100px;" alt=""/><br /><sub><b>James Brumond</b></sub></a><br /><a href="#plugin-kbjr" title="Plugin/utility libraries">🔌</a></td>
|
||||||
<td align="center"><a href="http://www.growingwiththeweb.com"><img src="https://avatars0.githubusercontent.com/u/2193314?v=4" width="100px;" alt=""/><br /><sub><b>Daniel Imms</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=Tyriar" title="Code">💻</a> <a href="#plugin-Tyriar" title="Plugin/utility libraries">🔌</a> <a href="https://github.com/Eugeny/terminus/commits?author=Tyriar" title="Tests">⚠️</a></td>
|
<td align="center"><a href="http://www.growingwiththeweb.com"><img src="https://avatars0.githubusercontent.com/u/2193314?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Daniel Imms</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=Tyriar" title="Code">💻</a> <a href="#plugin-Tyriar" title="Plugin/utility libraries">🔌</a> <a href="https://github.com/Eugeny/terminus/commits?author=Tyriar" title="Tests">⚠️</a></td>
|
||||||
<td align="center"><a href="https://github.com/baflo"><img src="https://avatars2.githubusercontent.com/u/834350?v=4" width="100px;" alt=""/><br /><sub><b>Florian Bachmann</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=baflo" title="Code">💻</a></td>
|
<td align="center"><a href="https://github.com/baflo"><img src="https://avatars2.githubusercontent.com/u/834350?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Florian Bachmann</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=baflo" title="Code">💻</a></td>
|
||||||
<td align="center"><a href="http://michael-kuehnel.de"><img src="https://avatars2.githubusercontent.com/u/441011?v=4" width="100px;" alt=""/><br /><sub><b>Michael Kühnel</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=mischah" title="Code">💻</a> <a href="#design-mischah" title="Design">🎨</a></td>
|
<td align="center"><a href="http://michael-kuehnel.de"><img src="https://avatars2.githubusercontent.com/u/441011?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Michael Kühnel</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=mischah" title="Code">💻</a> <a href="#design-mischah" title="Design">🎨</a></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td align="center"><a href="https://github.com/NieLeben"><img src="https://avatars3.githubusercontent.com/u/47182955?v=4" width="100px;" alt=""/><br /><sub><b>Tilmann Meyer</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=NieLeben" title="Code">💻</a></td>
|
<td align="center"><a href="https://github.com/NieLeben"><img src="https://avatars3.githubusercontent.com/u/47182955?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Tilmann Meyer</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=NieLeben" title="Code">💻</a></td>
|
||||||
<td align="center"><a href="http://www.jubeat.net"><img src="https://avatars3.githubusercontent.com/u/11289158?v=4" width="100px;" alt=""/><br /><sub><b>PM Extra</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/issues?q=author%3APMExtra" title="Bug reports">🐛</a></td>
|
<td align="center"><a href="http://www.jubeat.net"><img src="https://avatars3.githubusercontent.com/u/11289158?v=4?s=100" width="100px;" alt=""/><br /><sub><b>PM Extra</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/issues?q=author%3APMExtra" title="Bug reports">🐛</a></td>
|
||||||
<td align="center"><a href="https://jjuhas.keybase.pub//"><img src="https://avatars1.githubusercontent.com/u/6438760?v=4" width="100px;" alt=""/><br /><sub><b>Jonathan</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=IgnusG" title="Code">💻</a></td>
|
<td align="center"><a href="https://jjuhas.keybase.pub//"><img src="https://avatars1.githubusercontent.com/u/6438760?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Jonathan</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=IgnusG" title="Code">💻</a></td>
|
||||||
<td align="center"><a href="https://hans-koch.me"><img src="https://avatars0.githubusercontent.com/u/1093709?v=4" width="100px;" alt=""/><br /><sub><b>Hans Koch</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=hammster" title="Code">💻</a></td>
|
<td align="center"><a href="https://hans-koch.me"><img src="https://avatars0.githubusercontent.com/u/1093709?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Hans Koch</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=hammster" title="Code">💻</a></td>
|
||||||
<td align="center"><a href="http://thepuzzlemaker.info"><img src="https://avatars3.githubusercontent.com/u/12666617?v=4" width="100px;" alt=""/><br /><sub><b>Dak Smyth</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=ThePuzzlemaker" title="Code">💻</a></td>
|
<td align="center"><a href="http://thepuzzlemaker.info"><img src="https://avatars3.githubusercontent.com/u/12666617?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Dak Smyth</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=ThePuzzlemaker" title="Code">💻</a></td>
|
||||||
<td align="center"><a href="http://yfwz100.github.io"><img src="https://avatars2.githubusercontent.com/u/983211?v=4" width="100px;" alt=""/><br /><sub><b>Wang Zhi</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=yfwz100" title="Code">💻</a></td>
|
<td align="center"><a href="http://yfwz100.github.io"><img src="https://avatars2.githubusercontent.com/u/983211?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Wang Zhi</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=yfwz100" title="Code">💻</a></td>
|
||||||
<td align="center"><a href="https://github.com/jack1142"><img src="https://avatars0.githubusercontent.com/u/6032823?v=4" width="100px;" alt=""/><br /><sub><b>jack1142</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=jack1142" title="Code">💻</a></td>
|
<td align="center"><a href="https://github.com/jack1142"><img src="https://avatars0.githubusercontent.com/u/6032823?v=4?s=100" width="100px;" alt=""/><br /><sub><b>jack1142</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=jack1142" title="Code">💻</a></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td align="center"><a href="https://github.com/hdougie"><img src="https://avatars1.githubusercontent.com/u/450799?v=4" width="100px;" alt=""/><br /><sub><b>Howie Douglas</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=hdougie" title="Code">💻</a></td>
|
<td align="center"><a href="https://github.com/hdougie"><img src="https://avatars1.githubusercontent.com/u/450799?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Howie Douglas</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=hdougie" title="Code">💻</a></td>
|
||||||
<td align="center"><a href="https://chriskaczor.com"><img src="https://avatars2.githubusercontent.com/u/180906?v=4" width="100px;" alt=""/><br /><sub><b>Chris Kaczor</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=ckaczor" title="Code">💻</a></td>
|
<td align="center"><a href="https://chriskaczor.com"><img src="https://avatars2.githubusercontent.com/u/180906?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Chris Kaczor</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=ckaczor" title="Code">💻</a></td>
|
||||||
<td align="center"><a href="https://www.boxmein.net"><img src="https://avatars1.githubusercontent.com/u/358714?v=4" width="100px;" alt=""/><br /><sub><b>Johannes Kadak</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=boxmein" title="Code">💻</a></td>
|
<td align="center"><a href="https://www.boxmein.net"><img src="https://avatars1.githubusercontent.com/u/358714?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Johannes Kadak</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=boxmein" title="Code">💻</a></td>
|
||||||
<td align="center"><a href="https://github.com/LeSeulArtichaut"><img src="https://avatars1.githubusercontent.com/u/38361244?v=4" width="100px;" alt=""/><br /><sub><b>LeSeulArtichaut</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=LeSeulArtichaut" title="Code">💻</a></td>
|
<td align="center"><a href="https://github.com/LeSeulArtichaut"><img src="https://avatars1.githubusercontent.com/u/38361244?v=4?s=100" width="100px;" alt=""/><br /><sub><b>LeSeulArtichaut</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=LeSeulArtichaut" title="Code">💻</a></td>
|
||||||
<td align="center"><a href="https://github.com/CyrilTaylor"><img src="https://avatars0.githubusercontent.com/u/12631466?v=4" width="100px;" alt=""/><br /><sub><b>Cyril Taylor</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=CyrilTaylor" title="Code">💻</a></td>
|
<td align="center"><a href="https://github.com/CyrilTaylor"><img src="https://avatars0.githubusercontent.com/u/12631466?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Cyril Taylor</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=CyrilTaylor" title="Code">💻</a></td>
|
||||||
<td align="center"><a href="https://github.com/nstefanou"><img src="https://avatars3.githubusercontent.com/u/51129173?v=4" width="100px;" alt=""/><br /><sub><b>nstefanou</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=nstefanou" title="Code">💻</a> <a href="#plugin-nstefanou" title="Plugin/utility libraries">🔌</a></td>
|
<td align="center"><a href="https://github.com/nstefanou"><img src="https://avatars3.githubusercontent.com/u/51129173?v=4?s=100" width="100px;" alt=""/><br /><sub><b>nstefanou</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=nstefanou" title="Code">💻</a> <a href="#plugin-nstefanou" title="Plugin/utility libraries">🔌</a></td>
|
||||||
<td align="center"><a href="https://github.com/orin220444"><img src="https://avatars3.githubusercontent.com/u/30747229?v=4" width="100px;" alt=""/><br /><sub><b>orin220444</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=orin220444" title="Code">💻</a></td>
|
<td align="center"><a href="https://github.com/orin220444"><img src="https://avatars3.githubusercontent.com/u/30747229?v=4?s=100" width="100px;" alt=""/><br /><sub><b>orin220444</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=orin220444" title="Code">💻</a></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td align="center"><a href="https://github.com/Goobles"><img src="https://avatars3.githubusercontent.com/u/8776771?v=4" width="100px;" alt=""/><br /><sub><b>Gobius Dolhain</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=Goobles" title="Code">💻</a></td>
|
<td align="center"><a href="https://github.com/Goobles"><img src="https://avatars3.githubusercontent.com/u/8776771?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Gobius Dolhain</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=Goobles" title="Code">💻</a></td>
|
||||||
<td align="center"><a href="https://github.com/3l0w"><img src="https://avatars2.githubusercontent.com/u/37798980?v=4" width="100px;" alt=""/><br /><sub><b>Gwilherm Folliot</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=3l0w" title="Code">💻</a></td>
|
<td align="center"><a href="https://github.com/3l0w"><img src="https://avatars2.githubusercontent.com/u/37798980?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Gwilherm Folliot</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=3l0w" title="Code">💻</a></td>
|
||||||
<td align="center"><a href="https://github.com/Dimitory"><img src="https://avatars0.githubusercontent.com/u/475955?v=4" width="100px;" alt=""/><br /><sub><b>Dmitry Pronin</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=dimitory" title="Code">💻</a></td>
|
<td align="center"><a href="https://github.com/Dimitory"><img src="https://avatars0.githubusercontent.com/u/475955?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Dmitry Pronin</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=dimitory" title="Code">💻</a></td>
|
||||||
<td align="center"><a href="https://github.com/JonathanBeverley"><img src="https://avatars1.githubusercontent.com/u/20328966?v=4" width="100px;" alt=""/><br /><sub><b>Jonathan Beverley</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=JonathanBeverley" title="Code">💻</a></td>
|
<td align="center"><a href="https://github.com/JonathanBeverley"><img src="https://avatars1.githubusercontent.com/u/20328966?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Jonathan Beverley</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=JonathanBeverley" title="Code">💻</a></td>
|
||||||
<td align="center"><a href="https://github.com/zend"><img src="https://avatars1.githubusercontent.com/u/25160?v=4" width="100px;" alt=""/><br /><sub><b>Zenghai Liang</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=zend" title="Code">💻</a></td>
|
<td align="center"><a href="https://github.com/zend"><img src="https://avatars1.githubusercontent.com/u/25160?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Zenghai Liang</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=zend" title="Code">💻</a></td>
|
||||||
<td align="center"><a href="https://about.me/matishadow"><img src="https://avatars0.githubusercontent.com/u/9083085?v=4" width="100px;" alt=""/><br /><sub><b>Mateusz Tracz</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=matishadow" title="Code">💻</a></td>
|
<td align="center"><a href="https://about.me/matishadow"><img src="https://avatars0.githubusercontent.com/u/9083085?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Mateusz Tracz</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=matishadow" title="Code">💻</a></td>
|
||||||
<td align="center"><a href="https://zergpool.com"><img src="https://avatars3.githubusercontent.com/u/36234677?v=4" width="100px;" alt=""/><br /><sub><b>pinpin</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=pinpins" title="Code">💻</a></td>
|
<td align="center"><a href="https://zergpool.com"><img src="https://avatars3.githubusercontent.com/u/36234677?v=4?s=100" width="100px;" alt=""/><br /><sub><b>pinpin</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=pinpins" title="Code">💻</a></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td align="center"><a href="https://github.com/TakuroOnoda"><img src="https://avatars0.githubusercontent.com/u/1407926?v=4" width="100px;" alt=""/><br /><sub><b>Takuro Onoda</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=TakuroOnoda" title="Code">💻</a></td>
|
<td align="center"><a href="https://github.com/TakuroOnoda"><img src="https://avatars0.githubusercontent.com/u/1407926?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Takuro Onoda</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=TakuroOnoda" title="Code">💻</a></td>
|
||||||
|
<td align="center"><a href="https://github.com/frauhottelmann"><img src="https://avatars2.githubusercontent.com/u/902705?v=4?s=100" width="100px;" alt=""/><br /><sub><b>frauhottelmann</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=frauhottelmann" title="Code">💻</a></td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<!-- markdownlint-enable -->
|
<!-- markdownlint-restore -->
|
||||||
<!-- prettier-ignore-end -->
|
<!-- prettier-ignore-end -->
|
||||||
|
|
||||||
<!-- ALL-CONTRIBUTORS-LIST:END -->
|
<!-- ALL-CONTRIBUTORS-LIST:END -->
|
||||||
|
|
||||||
This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!
|
This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!
|
||||||
|
@@ -1,9 +1,11 @@
|
|||||||
import { app, ipcMain, Menu, Tray, shell, screen, globalShortcut, MenuItemConstructorOptions } from 'electron'
|
import { app, ipcMain, Menu, Tray, shell, screen, globalShortcut, MenuItemConstructorOptions } from 'electron'
|
||||||
|
import * as promiseIpc from 'electron-promise-ipc'
|
||||||
import { loadConfig } from './config'
|
import { loadConfig } from './config'
|
||||||
import { Window, WindowOptions } from './window'
|
import { Window, WindowOptions } from './window'
|
||||||
|
import { pluginManager } from './pluginManager'
|
||||||
|
|
||||||
export class Application {
|
export class Application {
|
||||||
private tray: Tray
|
private tray?: Tray
|
||||||
private windows: Window[] = []
|
private windows: Window[] = []
|
||||||
|
|
||||||
constructor () {
|
constructor () {
|
||||||
@@ -20,6 +22,14 @@ export class Application {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
;(promiseIpc as any).on('plugin-manager:install', (path, name, version) => {
|
||||||
|
return pluginManager.install(path, name, version)
|
||||||
|
})
|
||||||
|
|
||||||
|
;(promiseIpc as any).on('plugin-manager:uninstall', (path, name) => {
|
||||||
|
return pluginManager.uninstall(path, name)
|
||||||
|
})
|
||||||
|
|
||||||
const configData = loadConfig()
|
const configData = loadConfig()
|
||||||
if (process.platform === 'linux') {
|
if (process.platform === 'linux') {
|
||||||
app.commandLine.appendSwitch('no-sandbox')
|
app.commandLine.appendSwitch('no-sandbox')
|
||||||
@@ -65,7 +75,7 @@ export class Application {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onGlobalHotkey (): void {
|
onGlobalHotkey (): void {
|
||||||
if (this.windows.some(x => x.isFocused())) {
|
if (this.windows.some(x => x.isFocused() && x.isVisible())) {
|
||||||
for (const window of this.windows) {
|
for (const window of this.windows) {
|
||||||
window.hide()
|
window.hide()
|
||||||
}
|
}
|
||||||
@@ -121,10 +131,8 @@ export class Application {
|
|||||||
}
|
}
|
||||||
|
|
||||||
disableTray (): void {
|
disableTray (): void {
|
||||||
if (this.tray) {
|
this.tray?.destroy()
|
||||||
this.tray.destroy()
|
this.tray = null
|
||||||
this.tray = null
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hasWindows (): boolean {
|
hasWindows (): boolean {
|
||||||
@@ -139,7 +147,7 @@ export class Application {
|
|||||||
|
|
||||||
handleSecondInstance (argv: string[], cwd: string): void {
|
handleSecondInstance (argv: string[], cwd: string): void {
|
||||||
this.presentAllWindows()
|
this.presentAllWindows()
|
||||||
this.windows[this.windows.length - 1].handleSecondInstance(argv, cwd)
|
this.windows[this.windows.length - 1].passCliArguments(argv, cwd, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
private setupMenu () {
|
private setupMenu () {
|
||||||
|
@@ -5,7 +5,7 @@ export function parseArgs (argv: string[], cwd: string): any {
|
|||||||
argv = argv.slice(1)
|
argv = argv.slice(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
return require('yargs')
|
return require('yargs/yargs')(argv.slice(1))
|
||||||
.usage('terminus [command] [arguments]')
|
.usage('terminus [command] [arguments]')
|
||||||
.command('open [directory]', 'open a shell in a directory', {
|
.command('open [directory]', 'open a shell in a directory', {
|
||||||
directory: { type: 'string', 'default': cwd },
|
directory: { type: 'string', 'default': cwd },
|
||||||
@@ -41,5 +41,5 @@ export function parseArgs (argv: string[], cwd: string): any {
|
|||||||
type: 'boolean',
|
type: 'boolean',
|
||||||
})
|
})
|
||||||
.help('help')
|
.help('help')
|
||||||
.parse(argv.slice(1))
|
.parse()
|
||||||
}
|
}
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
import './portable'
|
import './portable'
|
||||||
|
import 'source-map-support/register'
|
||||||
import './sentry'
|
import './sentry'
|
||||||
import './lru'
|
import './lru'
|
||||||
import { app, ipcMain, Menu } from 'electron'
|
import { app, ipcMain, Menu } from 'electron'
|
||||||
@@ -52,7 +53,7 @@ if (argv.d) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
app.on('ready', () => {
|
app.on('ready', async () => {
|
||||||
if (process.platform === 'darwin') {
|
if (process.platform === 'darwin') {
|
||||||
app.dock.setMenu(Menu.buildFromTemplate([
|
app.dock.setMenu(Menu.buildFromTemplate([
|
||||||
{
|
{
|
||||||
@@ -64,5 +65,8 @@ app.on('ready', () => {
|
|||||||
]))
|
]))
|
||||||
}
|
}
|
||||||
application.init()
|
application.init()
|
||||||
application.newWindow({ hidden: argv.hidden })
|
|
||||||
|
const window = await application.newWindow({ hidden: argv.hidden })
|
||||||
|
await window.ready
|
||||||
|
window.passCliArguments(process.argv, process.cwd(), false)
|
||||||
})
|
})
|
||||||
|
40
app/lib/pluginManager.ts
Normal file
40
app/lib/pluginManager.ts
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
import { promisify } from 'util'
|
||||||
|
|
||||||
|
|
||||||
|
export class PluginManager {
|
||||||
|
npm: any
|
||||||
|
npmReady?: Promise<void>
|
||||||
|
|
||||||
|
async ensureLoaded (): Promise<void> {
|
||||||
|
if (!this.npmReady) {
|
||||||
|
this.npmReady = new Promise(resolve => {
|
||||||
|
const npm = require('npm')
|
||||||
|
npm.load(err => {
|
||||||
|
if (err) {
|
||||||
|
console.error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
npm.config.set('global', false)
|
||||||
|
this.npm = npm
|
||||||
|
resolve()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return this.npmReady
|
||||||
|
}
|
||||||
|
|
||||||
|
async install (path: string, name: string, version: string): Promise<void> {
|
||||||
|
await this.ensureLoaded()
|
||||||
|
this.npm.prefix = path
|
||||||
|
return promisify(this.npm.commands.install)([`${name}@${version}`])
|
||||||
|
}
|
||||||
|
|
||||||
|
async uninstall (path: string, name: string): Promise<void> {
|
||||||
|
await this.ensureLoaded()
|
||||||
|
this.npm.prefix = path
|
||||||
|
return promisify(this.npm.commands.remove)([name])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export const pluginManager = new PluginManager()
|
@@ -8,17 +8,15 @@ try {
|
|||||||
appPath = path.dirname(require('electron').remote.app.getPath('exe'))
|
appPath = path.dirname(require('electron').remote.app.getPath('exe'))
|
||||||
}
|
}
|
||||||
|
|
||||||
if (null != appPath) {
|
if (fs.existsSync(path.join(appPath, 'terminus-data'))) {
|
||||||
if (fs.existsSync(path.join(appPath, 'terminus-data'))) {
|
fs.renameSync(path.join(appPath, 'terminus-data'), path.join(appPath, 'data'))
|
||||||
fs.renameSync(path.join(appPath, 'terminus-data'), path.join(appPath, 'data'))
|
}
|
||||||
}
|
const portableData = path.join(appPath, 'data')
|
||||||
const portableData = path.join(appPath, 'data')
|
if (fs.existsSync(portableData)) {
|
||||||
if (fs.existsSync(portableData)) {
|
console.log('reset user data to ' + portableData)
|
||||||
console.log('reset user data to ' + portableData)
|
try {
|
||||||
try {
|
require('electron').app.setPath('userData', portableData)
|
||||||
require('electron').app.setPath('userData', portableData)
|
} catch {
|
||||||
} catch {
|
require('electron').remote.app.setPath('userData', portableData)
|
||||||
require('electron').remote.app.setPath('userData', portableData)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,7 +1,4 @@
|
|||||||
import * as glasstron from 'glasstron'
|
import * as glasstron from 'glasstron'
|
||||||
if (process.platform === 'win32' || process.platform === 'linux') {
|
|
||||||
glasstron.init()
|
|
||||||
}
|
|
||||||
|
|
||||||
import { Subject, Observable } from 'rxjs'
|
import { Subject, Observable } from 'rxjs'
|
||||||
import { debounceTime } from 'rxjs/operators'
|
import { debounceTime } from 'rxjs/operators'
|
||||||
@@ -9,6 +6,8 @@ import { BrowserWindow, app, ipcMain, Rectangle, Menu, screen, BrowserWindowCons
|
|||||||
import ElectronConfig = require('electron-config')
|
import ElectronConfig = require('electron-config')
|
||||||
import * as os from 'os'
|
import * as os from 'os'
|
||||||
import * as path from 'path'
|
import * as path from 'path'
|
||||||
|
import macOSRelease from 'macos-release'
|
||||||
|
import * as compareVersions from 'compare-versions'
|
||||||
|
|
||||||
import { parseArgs } from './cli'
|
import { parseArgs } from './cli'
|
||||||
import { loadConfig } from './config'
|
import { loadConfig } from './config'
|
||||||
@@ -27,13 +26,15 @@ abstract class GlasstronWindow extends BrowserWindow {
|
|||||||
abstract setBlur (_: boolean)
|
abstract setBlur (_: boolean)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const macOSVibrancyType = process.platform === 'darwin' ? compareVersions.compare(macOSRelease().version, '10.14', '>=') ? 'fullscreen-ui' : 'dark' : null
|
||||||
|
|
||||||
export class Window {
|
export class Window {
|
||||||
ready: Promise<void>
|
ready: Promise<void>
|
||||||
private visible = new Subject<boolean>()
|
private visible = new Subject<boolean>()
|
||||||
private closed = new Subject<void>()
|
private closed = new Subject<void>()
|
||||||
private window: GlasstronWindow
|
private window?: GlasstronWindow
|
||||||
private windowConfig: ElectronConfig
|
private windowConfig: ElectronConfig
|
||||||
private windowBounds: Rectangle
|
private windowBounds?: Rectangle
|
||||||
private closing = false
|
private closing = false
|
||||||
private lastVibrancy: {enabled: boolean, type?: string} | null = null
|
private lastVibrancy: {enabled: boolean, type?: string} | null = null
|
||||||
private disableVibrancyWhileDragging = false
|
private disableVibrancyWhileDragging = false
|
||||||
@@ -45,7 +46,7 @@ export class Window {
|
|||||||
constructor (options?: WindowOptions) {
|
constructor (options?: WindowOptions) {
|
||||||
this.configStore = loadConfig()
|
this.configStore = loadConfig()
|
||||||
|
|
||||||
options = options || {}
|
options = options ?? {}
|
||||||
|
|
||||||
this.windowConfig = new ElectronConfig({ name: 'window' })
|
this.windowConfig = new ElectronConfig({ name: 'window' })
|
||||||
this.windowBounds = this.windowConfig.get('windowBoundaries')
|
this.windowBounds = this.windowConfig.get('windowBoundaries')
|
||||||
@@ -62,7 +63,9 @@ export class Window {
|
|||||||
preload: path.join(__dirname, 'sentry.js'),
|
preload: path.join(__dirname, 'sentry.js'),
|
||||||
backgroundThrottling: false,
|
backgroundThrottling: false,
|
||||||
enableRemoteModule: true,
|
enableRemoteModule: true,
|
||||||
|
contextIsolation: false,
|
||||||
},
|
},
|
||||||
|
maximizable: true,
|
||||||
frame: false,
|
frame: false,
|
||||||
show: false,
|
show: false,
|
||||||
backgroundColor: '#00000000',
|
backgroundColor: '#00000000',
|
||||||
@@ -89,11 +92,15 @@ export class Window {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.window = new glasstron.BrowserWindow(bwOptions)
|
if (process.platform === 'darwin') {
|
||||||
|
this.window = new BrowserWindow(bwOptions) as GlasstronWindow
|
||||||
|
} else {
|
||||||
|
this.window = new glasstron.BrowserWindow(bwOptions)
|
||||||
|
}
|
||||||
|
|
||||||
this.window.once('ready-to-show', () => {
|
this.window.once('ready-to-show', () => {
|
||||||
if (process.platform === 'darwin') {
|
if (process.platform === 'darwin') {
|
||||||
this.window.setVibrancy('window')
|
this.window.setVibrancy(macOSVibrancyType)
|
||||||
} else if (process.platform === 'win32' && (this.configStore.appearance || {}).vibrancy) {
|
} else if (process.platform === 'win32' && (this.configStore.appearance || {}).vibrancy) {
|
||||||
this.setVibrancy(true)
|
this.setVibrancy(true)
|
||||||
}
|
}
|
||||||
@@ -141,7 +148,11 @@ export class Window {
|
|||||||
if (process.platform === 'win32') {
|
if (process.platform === 'win32') {
|
||||||
if (parseFloat(os.release()) >= 10) {
|
if (parseFloat(os.release()) >= 10) {
|
||||||
this.window.blurType = enabled ? type === 'fluent' ? 'acrylic' : 'blurbehind' : null
|
this.window.blurType = enabled ? type === 'fluent' ? 'acrylic' : 'blurbehind' : null
|
||||||
this.window.setBlur(enabled)
|
try {
|
||||||
|
this.window.setBlur(enabled)
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to set window blur', error)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
DwmEnableBlurBehindWindow(this.window, enabled)
|
DwmEnableBlurBehindWindow(this.window, enabled)
|
||||||
}
|
}
|
||||||
@@ -149,7 +160,7 @@ export class Window {
|
|||||||
this.window.setBackgroundColor(enabled ? '#00000000' : '#131d27')
|
this.window.setBackgroundColor(enabled ? '#00000000' : '#131d27')
|
||||||
this.window.setBlur(enabled)
|
this.window.setBlur(enabled)
|
||||||
} else {
|
} else {
|
||||||
this.window.setVibrancy(enabled ? 'dark' : null as any) // electron issue 20269
|
this.window.setVibrancy(enabled ? macOSVibrancyType : null)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -180,6 +191,10 @@ export class Window {
|
|||||||
return this.window.isFocused()
|
return this.window.isFocused()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isVisible (): boolean {
|
||||||
|
return this.window.isVisible()
|
||||||
|
}
|
||||||
|
|
||||||
hide (): void {
|
hide (): void {
|
||||||
if (process.platform === 'darwin') {
|
if (process.platform === 'darwin') {
|
||||||
// Lose focus
|
// Lose focus
|
||||||
@@ -215,8 +230,8 @@ export class Window {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handleSecondInstance (argv: string[], cwd: string): void {
|
passCliArguments (argv: string[], cwd: string, secondInstance: boolean): void {
|
||||||
this.send('host:second-instance', parseArgs(argv, cwd), cwd)
|
this.send('cli', parseArgs(argv, cwd), cwd, secondInstance)
|
||||||
}
|
}
|
||||||
|
|
||||||
private setupWindowManagement () {
|
private setupWindowManagement () {
|
||||||
|
@@ -25,16 +25,16 @@
|
|||||||
"electron-config": "2.0.0",
|
"electron-config": "2.0.0",
|
||||||
"electron-debug": "^3.0.1",
|
"electron-debug": "^3.0.1",
|
||||||
"electron-is-dev": "1.1.0",
|
"electron-is-dev": "1.1.0",
|
||||||
|
"electron-promise-ipc": "^2.2.4",
|
||||||
"fontmanager-redux": "1.0.0",
|
"fontmanager-redux": "1.0.0",
|
||||||
"glasstron": "0.0.5",
|
"glasstron": "0.0.6",
|
||||||
"js-yaml": "3.14.0",
|
"js-yaml": "3.14.0",
|
||||||
"keytar": "^7.2.0",
|
"keytar": "^7.2.0",
|
||||||
"mz": "^2.7.0",
|
"mz": "^2.7.0",
|
||||||
"ngx-toastr": "^12.0.1",
|
"ngx-toastr": "^12.0.1",
|
||||||
"npm": "7.0.15",
|
"npm": "6",
|
||||||
"path": "0.12.7",
|
"path": "0.12.7",
|
||||||
"rxjs": "^6.5.5",
|
"rxjs": "^6.5.5",
|
||||||
"rxjs-compat": "^6.6.0",
|
|
||||||
"yargs": "^15.4.1",
|
"yargs": "^15.4.1",
|
||||||
"zone.js": "^0.11.3"
|
"zone.js": "^0.11.3"
|
||||||
},
|
},
|
||||||
@@ -48,7 +48,8 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/mz": "0.0.32",
|
"@types/mz": "0.0.32",
|
||||||
"@types/node": "14.14.14",
|
"@types/node": "14.14.14",
|
||||||
"node-abi": "2.19.3"
|
"node-abi": "2.19.3",
|
||||||
|
"source-map-support": "^0.5.19"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"terminus-community-color-schemes": "*",
|
"terminus-community-color-schemes": "*",
|
||||||
|
@@ -58,8 +58,8 @@ findPlugins().then(async plugins => {
|
|||||||
window['safeModeReason'] = error
|
window['safeModeReason'] = error
|
||||||
try {
|
try {
|
||||||
await bootstrap(plugins, true)
|
await bootstrap(plugins, true)
|
||||||
} catch (error) {
|
} catch (error2) {
|
||||||
console.error('Bootstrap failed:', error)
|
console.error('Bootstrap failed:', error2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@@ -3,13 +3,13 @@ import * as path from 'path'
|
|||||||
const nodeModule = require('module') // eslint-disable-line @typescript-eslint/no-var-requires
|
const nodeModule = require('module') // eslint-disable-line @typescript-eslint/no-var-requires
|
||||||
const nodeRequire = (global as any).require
|
const nodeRequire = (global as any).require
|
||||||
|
|
||||||
function normalizePath (path: string): string {
|
function normalizePath (p: string): string {
|
||||||
const cygwinPrefix = '/cygdrive/'
|
const cygwinPrefix = '/cygdrive/'
|
||||||
if (path.startsWith(cygwinPrefix)) {
|
if (p.startsWith(cygwinPrefix)) {
|
||||||
path = path.substring(cygwinPrefix.length).replace('/', '\\')
|
p = p.substring(cygwinPrefix.length).replace('/', '\\')
|
||||||
path = path[0] + ':' + path.substring(1)
|
p = p[0] + ':' + p.substring(1)
|
||||||
}
|
}
|
||||||
return path
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
global['module'].paths.map((x: string) => nodeModule.globalPaths.push(normalizePath(x)))
|
global['module'].paths.map((x: string) => nodeModule.globalPaths.push(normalizePath(x)))
|
||||||
@@ -63,7 +63,6 @@ const builtinModules = [
|
|||||||
'ngx-toastr',
|
'ngx-toastr',
|
||||||
'rxjs',
|
'rxjs',
|
||||||
'rxjs/operators',
|
'rxjs/operators',
|
||||||
'rxjs-compat/Subject',
|
|
||||||
'terminus-core',
|
'terminus-core',
|
||||||
'terminus-settings',
|
'terminus-settings',
|
||||||
'terminus-terminal',
|
'terminus-terminal',
|
||||||
|
@@ -35,12 +35,15 @@ module.exports = {
|
|||||||
externals: {
|
externals: {
|
||||||
electron: 'commonjs electron',
|
electron: 'commonjs electron',
|
||||||
'electron-config': 'commonjs electron-config',
|
'electron-config': 'commonjs electron-config',
|
||||||
|
'electron-promise-ipc': 'commonjs electron-promise-ipc',
|
||||||
'electron-vibrancy': 'commonjs electron-vibrancy',
|
'electron-vibrancy': 'commonjs electron-vibrancy',
|
||||||
fs: 'commonjs fs',
|
fs: 'commonjs fs',
|
||||||
glasstron: 'commonjs glasstron',
|
glasstron: 'commonjs glasstron',
|
||||||
mz: 'commonjs mz',
|
mz: 'commonjs mz',
|
||||||
|
npm: 'commonjs npm',
|
||||||
path: 'commonjs path',
|
path: 'commonjs path',
|
||||||
yargs: 'commonjs yargs',
|
util: 'commonjs util',
|
||||||
|
'source-map-support': 'commonjs source-map-support',
|
||||||
'windows-swca': 'commonjs windows-swca',
|
'windows-swca': 'commonjs windows-swca',
|
||||||
'windows-blurbehind': 'commonjs windows-blurbehind',
|
'windows-blurbehind': 'commonjs windows-blurbehind',
|
||||||
},
|
},
|
||||||
@@ -50,4 +53,6 @@ module.exports = {
|
|||||||
'process.type': '"main"',
|
'process.type': '"main"',
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
|
// Ignore warnings due to yarg's dynamic module loading
|
||||||
|
ignoreWarnings: [/node_modules\/yargs/],
|
||||||
}
|
}
|
||||||
|
2823
app/yarn.lock
2823
app/yarn.lock
File diff suppressed because it is too large
Load Diff
@@ -6,8 +6,27 @@ npmRebuild: false
|
|||||||
afterSign: "./build/mac/afterSignHook.js"
|
afterSign: "./build/mac/afterSignHook.js"
|
||||||
afterAllArtifactBuild: "./build/mac/afterBuildHook.js"
|
afterAllArtifactBuild: "./build/mac/afterBuildHook.js"
|
||||||
files:
|
files:
|
||||||
- "**/*"
|
- '**/*'
|
||||||
- dist
|
- dist
|
||||||
|
- '!src'
|
||||||
|
- '!**/node_modules/*/{CHANGELOG.md,README.md,README,readme.md,readme}'
|
||||||
|
- '!**/node_modules/*/{test,__tests__,tests,powered-test,example,examples,docs}'
|
||||||
|
- '!**/node_modules/@angular/common/locales'
|
||||||
|
- '!**/node_modules/@angular/compiler/src'
|
||||||
|
- '!**/node_modules/node-gyp'
|
||||||
|
- '!**/node_modules/**/*.d.ts'
|
||||||
|
- '!**/node_modules/**/*.map'
|
||||||
|
- '!**/node_modules/**/include/node'
|
||||||
|
- '!**/node_modules/.bin'
|
||||||
|
- '!**/node_modules/*/*/{esm5,fesm5,esm2015,fesm2015,_esm2015,_fesm2015}'
|
||||||
|
- '!**/*.{woff,ttf,otf,eot}'
|
||||||
|
- '!**/*.{iml,o,hprof,orig,pyc,pyo,rbc,swp,csproj,sln,xproj}'
|
||||||
|
- '!.editorconfig'
|
||||||
|
- '!**/._*'
|
||||||
|
- '!**/{.DS_Store,.git,.hg,.svn,CVS,RCS,SCCS,.gitignore,.gitattributes}'
|
||||||
|
- '!**/{__pycache__,thumbs.db,.flowconfig,.idea,.vs,.nyc_output}'
|
||||||
|
- '!**/{appveyor.yml,.travis.yml,circle.yml}'
|
||||||
|
- '!**/{npm-debug.log,yarn.lock,.yarn-integrity,.yarn-metadata.json'
|
||||||
extraResources:
|
extraResources:
|
||||||
- builtin-plugins
|
- builtin-plugins
|
||||||
- extras
|
- extras
|
||||||
@@ -22,6 +41,7 @@ nsis:
|
|||||||
oneClick: false
|
oneClick: false
|
||||||
artifactName: terminus-${version}-setup.${ext}
|
artifactName: terminus-${version}-setup.${ext}
|
||||||
installerIcon: "./build/windows/icon.ico"
|
installerIcon: "./build/windows/icon.ico"
|
||||||
|
allowToChangeInstallationDirectory: true
|
||||||
|
|
||||||
mac:
|
mac:
|
||||||
category: public.app-category.video
|
category: public.app-category.video
|
||||||
|
@@ -13,11 +13,12 @@
|
|||||||
"@typescript-eslint/parser": "^4.11.0",
|
"@typescript-eslint/parser": "^4.11.0",
|
||||||
"apply-loader": "2.0.0",
|
"apply-loader": "2.0.0",
|
||||||
"awesome-typescript-loader": "^5.2.1",
|
"awesome-typescript-loader": "^5.2.1",
|
||||||
|
"compare-versions": "^3.6.0",
|
||||||
"core-js": "^3.8.1",
|
"core-js": "^3.8.1",
|
||||||
"cross-env": "7.0.2",
|
"cross-env": "7.0.2",
|
||||||
"css-loader": "3.4.2",
|
"css-loader": "3.4.2",
|
||||||
"electron": "^11.1.1",
|
"electron": "12.0.0-beta.16",
|
||||||
"electron-builder": "22.10.3",
|
"electron-builder": "22.10.4",
|
||||||
"electron-download": "^4.1.1",
|
"electron-download": "^4.1.1",
|
||||||
"electron-installer-snap": "^5.1.0",
|
"electron-installer-snap": "^5.1.0",
|
||||||
"electron-notarize": "^1.0.0",
|
"electron-notarize": "^1.0.0",
|
||||||
@@ -29,6 +30,7 @@
|
|||||||
"html-loader": "0.5.5",
|
"html-loader": "0.5.5",
|
||||||
"json-loader": "0.5.7",
|
"json-loader": "0.5.7",
|
||||||
"lru-cache": "^6.0.0",
|
"lru-cache": "^6.0.0",
|
||||||
|
"macos-release": "^2.4.1",
|
||||||
"node-abi": "^2.19.3",
|
"node-abi": "^2.19.3",
|
||||||
"node-gyp": "^7.1.2",
|
"node-gyp": "^7.1.2",
|
||||||
"node-sass": "^5.0.0",
|
"node-sass": "^5.0.0",
|
||||||
@@ -45,7 +47,7 @@
|
|||||||
"source-code-pro": "^2.30.2",
|
"source-code-pro": "^2.30.2",
|
||||||
"source-sans-pro": "3.6.0",
|
"source-sans-pro": "3.6.0",
|
||||||
"ssh2-streams": "^0.4.10",
|
"ssh2-streams": "^0.4.10",
|
||||||
"style-loader": "^1.3.0",
|
"style-loader": "^2.0.0",
|
||||||
"svg-inline-loader": "^0.8.2",
|
"svg-inline-loader": "^0.8.2",
|
||||||
"to-string-loader": "1.1.6",
|
"to-string-loader": "1.1.6",
|
||||||
"tslib": "^2.0.3",
|
"tslib": "^2.0.3",
|
||||||
|
24
scripts/sentry-upload.js
Executable file
24
scripts/sentry-upload.js
Executable file
@@ -0,0 +1,24 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
const sh = require('shelljs')
|
||||||
|
const vars = require('./vars')
|
||||||
|
|
||||||
|
const sentryCli = process.platform === 'win32' ? 'node_modules\\.bin\\sentry-cli.cmd' : 'sentry-cli'
|
||||||
|
|
||||||
|
sh.exec(`${sentryCli} releases new ${vars.version}`)
|
||||||
|
|
||||||
|
if (process.platform === 'darwin') {
|
||||||
|
for (const path of [
|
||||||
|
'app/node_modules/@serialport/bindings/build/Release/bindings.node',
|
||||||
|
'app/node_modules/@terminus-term/node-pty/build/Release/pty.node',
|
||||||
|
'app/node_modules/fontmanager-redux/build/Release/fontmanager.node',
|
||||||
|
'app/node_modules/macos-native-processlist/build/Release/native.node',
|
||||||
|
]) {
|
||||||
|
sh.exec('dsymutil ' + path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sh.exec(`${sentryCli} upload-dif app/node_modules`)
|
||||||
|
sh.exec(`${sentryCli} releases set-commits --auto ${vars.version}`)
|
||||||
|
for (const p of vars.builtinPlugins) {
|
||||||
|
sh.exec(`${sentryCli} releases files ${vars.version} upload-sourcemaps ${p}/dist -u ${p}/dist/ -d ${process.platform}-${p}`)
|
||||||
|
}
|
@@ -1,14 +1,14 @@
|
|||||||
import { Injectable } from '@angular/core'
|
import { Injectable } from '@angular/core'
|
||||||
import { TerminalColorSchemeProvider, TerminalColorScheme } from 'terminus-terminal'
|
import { TerminalColorSchemeProvider, TerminalColorScheme } from 'terminus-terminal'
|
||||||
|
|
||||||
const schemeContents = require.context('../schemes/', true, /.*/)
|
const schemeContents = require.context('../schemes/', false, /.*/)
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class ColorSchemes extends TerminalColorSchemeProvider {
|
export class ColorSchemes extends TerminalColorSchemeProvider {
|
||||||
async getSchemes (): Promise<TerminalColorScheme[]> {
|
async getSchemes (): Promise<TerminalColorScheme[]> {
|
||||||
const schemes: TerminalColorScheme[] = []
|
const schemes: TerminalColorScheme[] = []
|
||||||
|
|
||||||
schemeContents.keys().forEach(schemeFile => {
|
schemeContents.keys().filter(x => !x.startsWith('./')).forEach(schemeFile => {
|
||||||
const lines = (schemeContents(schemeFile).default as string).split('\n')
|
const lines = (schemeContents(schemeFile).default as string).split('\n')
|
||||||
|
|
||||||
// process #define variables
|
// process #define variables
|
||||||
|
@@ -8,7 +8,5 @@ export interface HotkeyDescription {
|
|||||||
* must also provide the `hotkeys.foo` config options with the default values
|
* must also provide the `hotkeys.foo` config options with the default values
|
||||||
*/
|
*/
|
||||||
export abstract class HotkeyProvider {
|
export abstract class HotkeyProvider {
|
||||||
hotkeys: HotkeyDescription[] = []
|
|
||||||
|
|
||||||
abstract provide (): Promise<HotkeyDescription[]>
|
abstract provide (): Promise<HotkeyDescription[]>
|
||||||
}
|
}
|
||||||
|
@@ -26,8 +26,8 @@ $side-tab-width: 200px;
|
|||||||
|
|
||||||
.content {
|
.content {
|
||||||
width: 100vw;
|
width: 100vw;
|
||||||
height: 100vh;
|
flex: 1 1 0;
|
||||||
flex: auto;
|
min-height: 0;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column-reverse;
|
flex-direction: column-reverse;
|
||||||
|
|
||||||
@@ -66,6 +66,10 @@ $side-tab-width: 200px;
|
|||||||
.drag-space {
|
.drag-space {
|
||||||
flex: auto;
|
flex: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&>.inset {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -92,7 +96,7 @@ $side-tab-width: 200px;
|
|||||||
color: #aaa;
|
color: #aaa;
|
||||||
border: none;
|
border: none;
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
|
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
||||||
&.dropdown-toggle::after {
|
&.dropdown-toggle::after {
|
||||||
@@ -121,7 +125,6 @@ $side-tab-width: 200px;
|
|||||||
width: 85px;
|
width: 85px;
|
||||||
height: $tabs-height;
|
height: $tabs-height;
|
||||||
flex: none;
|
flex: none;
|
||||||
opacity: 0;
|
|
||||||
-webkit-app-region: drag;
|
-webkit-app-region: drag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -229,8 +229,8 @@ export class AppRootComponent {
|
|||||||
buttons = buttons.concat(provider.provide())
|
buttons = buttons.concat(provider.provide())
|
||||||
})
|
})
|
||||||
return buttons
|
return buttons
|
||||||
.filter(button => (button.weight || 0) > 0 === aboveZero)
|
.filter(button => (button.weight ?? 0) > 0 === aboveZero)
|
||||||
.sort((a: ToolbarButton, b: ToolbarButton) => (a.weight || 0) - (b.weight || 0))
|
.sort((a: ToolbarButton, b: ToolbarButton) => (a.weight ?? 0) - (b.weight ?? 0))
|
||||||
}
|
}
|
||||||
|
|
||||||
private updateVibrancy () {
|
private updateVibrancy () {
|
||||||
|
@@ -50,7 +50,7 @@ export class SelectorModalComponent<T> {
|
|||||||
this.filteredOptions = this.options.filter(x => !x.freeInputPattern)
|
this.filteredOptions = this.options.filter(x => !x.freeInputPattern)
|
||||||
} else {
|
} else {
|
||||||
// eslint-disable-next-line @typescript-eslint/restrict-plus-operands
|
// eslint-disable-next-line @typescript-eslint/restrict-plus-operands
|
||||||
this.filteredOptions = this.options.filter(x => x.freeInputPattern || (x.name + (x.description || '')).toLowerCase().includes(f))
|
this.filteredOptions = this.options.filter(x => x.freeInputPattern ?? (x.name + (x.description ?? '')).toLowerCase().includes(f))
|
||||||
}
|
}
|
||||||
this.selectedIndex = Math.max(0, this.selectedIndex)
|
this.selectedIndex = Math.max(0, this.selectedIndex)
|
||||||
this.selectedIndex = Math.min(this.filteredOptions.length - 1, this.selectedIndex)
|
this.selectedIndex = Math.min(this.filteredOptions.length - 1, this.selectedIndex)
|
||||||
@@ -72,7 +72,7 @@ export class SelectorModalComponent<T> {
|
|||||||
this.modalInstance.dismiss()
|
this.modalInstance.dismiss()
|
||||||
}
|
}
|
||||||
|
|
||||||
iconIsSVG (icon: string): boolean {
|
iconIsSVG (icon?: string): boolean {
|
||||||
return icon?.startsWith('<')
|
return icon?.startsWith('<') ?? false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -161,7 +161,7 @@ export class SplitTabComponent extends BaseTabComponent implements AfterViewInit
|
|||||||
_allFocusMode = false
|
_allFocusMode = false
|
||||||
|
|
||||||
/** @hidden */
|
/** @hidden */
|
||||||
private focusedTab: BaseTabComponent
|
private focusedTab: BaseTabComponent|null = null
|
||||||
private maximizedTab: BaseTabComponent|null = null
|
private maximizedTab: BaseTabComponent|null = null
|
||||||
private hotkeysSubscription: Subscription
|
private hotkeysSubscription: Subscription
|
||||||
private viewRefs: Map<BaseTabComponent, EmbeddedViewRef<any>> = new Map()
|
private viewRefs: Map<BaseTabComponent, EmbeddedViewRef<any>> = new Map()
|
||||||
@@ -211,7 +211,7 @@ 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.hotkeysSubscription = this.hotkeys.matchedHotkey.subscribe(hotkey => {
|
this.hotkeysSubscription = this.hotkeys.matchedHotkey.subscribe(hotkey => {
|
||||||
if (!this.hasFocus) {
|
if (!this.hasFocus || !this.focusedTab) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
switch (hotkey) {
|
switch (hotkey) {
|
||||||
@@ -280,7 +280,7 @@ export class SplitTabComponent extends BaseTabComponent implements AfterViewInit
|
|||||||
return this.root.getAllTabs()
|
return this.root.getAllTabs()
|
||||||
}
|
}
|
||||||
|
|
||||||
getFocusedTab (): BaseTabComponent {
|
getFocusedTab (): BaseTabComponent|null {
|
||||||
return this.focusedTab
|
return this.focusedTab
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -295,10 +295,8 @@ export class SplitTabComponent extends BaseTabComponent implements AfterViewInit
|
|||||||
x.emitBlurred()
|
x.emitBlurred()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (tab) {
|
tab.emitFocused()
|
||||||
tab.emitFocused()
|
this.focusChanged.next(tab)
|
||||||
this.focusChanged.next(tab)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.maximizedTab !== tab) {
|
if (this.maximizedTab !== tab) {
|
||||||
this.maximizedTab = null
|
this.maximizedTab = null
|
||||||
@@ -314,7 +312,7 @@ export class SplitTabComponent extends BaseTabComponent implements AfterViewInit
|
|||||||
/**
|
/**
|
||||||
* Focuses the first available tab inside the given [[SplitContainer]]
|
* Focuses the first available tab inside the given [[SplitContainer]]
|
||||||
*/
|
*/
|
||||||
focusAnyIn (parent: BaseTabComponent | SplitContainer): void {
|
focusAnyIn (parent?: BaseTabComponent | SplitContainer): void {
|
||||||
if (!parent) {
|
if (!parent) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -331,7 +329,7 @@ export class SplitTabComponent extends BaseTabComponent implements AfterViewInit
|
|||||||
async addTab (tab: BaseTabComponent, relative: BaseTabComponent|null, side: SplitDirection): Promise<void> {
|
async addTab (tab: BaseTabComponent, relative: BaseTabComponent|null, side: SplitDirection): Promise<void> {
|
||||||
tab.parent = this
|
tab.parent = this
|
||||||
|
|
||||||
let target = (relative ? this.getParentOf(relative) : null) || this.root
|
let target = (relative ? this.getParentOf(relative) : null) ?? this.root
|
||||||
let insertIndex = relative ? target.children.indexOf(relative) : -1
|
let insertIndex = relative ? target.children.indexOf(relative) : -1
|
||||||
|
|
||||||
if (
|
if (
|
||||||
@@ -398,6 +396,10 @@ export class SplitTabComponent extends BaseTabComponent implements AfterViewInit
|
|||||||
* Moves focus in the given direction
|
* Moves focus in the given direction
|
||||||
*/
|
*/
|
||||||
navigate (dir: SplitDirection): void {
|
navigate (dir: SplitDirection): void {
|
||||||
|
if (!this.focusedTab) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
let rel: BaseTabComponent | SplitContainer = this.focusedTab
|
let rel: BaseTabComponent | SplitContainer = this.focusedTab
|
||||||
let parent = this.getParentOf(rel)
|
let parent = this.getParentOf(rel)
|
||||||
if (!parent) {
|
if (!parent) {
|
||||||
@@ -442,7 +444,7 @@ export class SplitTabComponent extends BaseTabComponent implements AfterViewInit
|
|||||||
* @returns the immediate parent of `tab`
|
* @returns the immediate parent of `tab`
|
||||||
*/
|
*/
|
||||||
getParentOf (tab: BaseTabComponent | SplitContainer, root?: SplitContainer): SplitContainer|null {
|
getParentOf (tab: BaseTabComponent | SplitContainer, root?: SplitContainer): SplitContainer|null {
|
||||||
root = root || this.root
|
root = root ?? this.root
|
||||||
for (const child of root.children) {
|
for (const child of root.children) {
|
||||||
if (child instanceof SplitContainer) {
|
if (child instanceof SplitContainer) {
|
||||||
const r = this.getParentOf(tab, child)
|
const r = this.getParentOf(tab, child)
|
||||||
@@ -469,7 +471,7 @@ export class SplitTabComponent extends BaseTabComponent implements AfterViewInit
|
|||||||
|
|
||||||
/** @hidden */
|
/** @hidden */
|
||||||
async getCurrentProcess (): Promise<BaseTabProcess|null> {
|
async getCurrentProcess (): Promise<BaseTabProcess|null> {
|
||||||
return (await Promise.all(this.getAllTabs().map(x => x.getCurrentProcess()))).find(x => !!x) || null
|
return (await Promise.all(this.getAllTabs().map(x => x.getCurrentProcess()))).find(x => !!x) ?? null
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @hidden */
|
/** @hidden */
|
||||||
@@ -518,7 +520,7 @@ export class SplitTabComponent extends BaseTabComponent implements AfterViewInit
|
|||||||
|
|
||||||
private layoutInternal (root: SplitContainer, x: number, y: number, w: number, h: number) {
|
private layoutInternal (root: SplitContainer, x: number, y: number, w: number, h: number) {
|
||||||
const size = root.orientation === 'v' ? h : w
|
const size = root.orientation === 'v' ? h : w
|
||||||
const sizes = root.ratios.map(x => x * size)
|
const sizes = root.ratios.map(ratio => ratio * size)
|
||||||
|
|
||||||
root.x = x
|
root.x = x
|
||||||
root.y = y
|
root.y = y
|
||||||
@@ -598,7 +600,7 @@ export class SplitTabComponent extends BaseTabComponent implements AfterViewInit
|
|||||||
@Injectable()
|
@Injectable()
|
||||||
export class SplitTabRecoveryProvider extends TabRecoveryProvider {
|
export class SplitTabRecoveryProvider extends TabRecoveryProvider {
|
||||||
async recover (recoveryToken: RecoveryToken): Promise<RecoveredTab|null> {
|
async recover (recoveryToken: RecoveryToken): Promise<RecoveredTab|null> {
|
||||||
if (recoveryToken && recoveryToken.type === 'app:split-tab') {
|
if (recoveryToken.type === 'app:split-tab') {
|
||||||
return {
|
return {
|
||||||
type: SplitTabComponent,
|
type: SplitTabComponent,
|
||||||
options: { _recoveredState: recoveryToken },
|
options: { _recoveredState: recoveryToken },
|
||||||
|
@@ -34,8 +34,8 @@ export class SplitTabSpannerComponent {
|
|||||||
let current = start
|
let current = start
|
||||||
const oldPosition: number = this.isVertical ? this.element.nativeElement.offsetTop : this.element.nativeElement.offsetLeft
|
const oldPosition: number = this.isVertical ? this.element.nativeElement.offsetTop : this.element.nativeElement.offsetLeft
|
||||||
|
|
||||||
const dragHandler = (e: MouseEvent) => {
|
const dragHandler = (dragEvent: MouseEvent) => {
|
||||||
current = this.isVertical ? e.pageY : e.pageX
|
current = this.isVertical ? dragEvent.pageY : dragEvent.pageX
|
||||||
const newPosition = oldPosition + (current - start)
|
const newPosition = oldPosition + (current - start)
|
||||||
if (this.isVertical) {
|
if (this.isVertical) {
|
||||||
this.element.nativeElement.style.top = `${newPosition - this.marginOffset}px`
|
this.element.nativeElement.style.top = `${newPosition - this.marginOffset}px`
|
||||||
|
@@ -26,10 +26,10 @@ export class StartPageComponent {
|
|||||||
.map(provider => provider.provide())
|
.map(provider => provider.provide())
|
||||||
.reduce((a, b) => a.concat(b))
|
.reduce((a, b) => a.concat(b))
|
||||||
.filter(x => !!x.click)
|
.filter(x => !!x.click)
|
||||||
.sort((a: ToolbarButton, b: ToolbarButton) => (a.weight || 0) - (b.weight || 0))
|
.sort((a: ToolbarButton, b: ToolbarButton) => (a.weight ?? 0) - (b.weight ?? 0))
|
||||||
}
|
}
|
||||||
|
|
||||||
sanitizeIcon (icon: string): any {
|
sanitizeIcon (icon?: string): any {
|
||||||
return this.domSanitizer.bypassSecurityTrustHtml(icon || '')
|
return this.domSanitizer.bypassSecurityTrustHtml(icon ?? '')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -46,13 +46,13 @@ class CompletionObserver {
|
|||||||
export class AppService {
|
export class AppService {
|
||||||
tabs: BaseTabComponent[] = []
|
tabs: BaseTabComponent[] = []
|
||||||
|
|
||||||
get activeTab (): BaseTabComponent { return this._activeTab }
|
get activeTab (): BaseTabComponent|null { return this._activeTab ?? null }
|
||||||
|
|
||||||
private lastTabIndex = 0
|
private lastTabIndex = 0
|
||||||
private _activeTab: BaseTabComponent
|
private _activeTab: BaseTabComponent | null = null
|
||||||
private closedTabsStack: RecoveryToken[] = []
|
private closedTabsStack: RecoveryToken[] = []
|
||||||
|
|
||||||
private activeTabChange = new Subject<BaseTabComponent>()
|
private activeTabChange = new Subject<BaseTabComponent|null>()
|
||||||
private tabsChanged = new Subject<void>()
|
private tabsChanged = new Subject<void>()
|
||||||
private tabOpened = new Subject<BaseTabComponent>()
|
private tabOpened = new Subject<BaseTabComponent>()
|
||||||
private tabClosed = new Subject<BaseTabComponent>()
|
private tabClosed = new Subject<BaseTabComponent>()
|
||||||
@@ -60,7 +60,7 @@ export class AppService {
|
|||||||
|
|
||||||
private completionObservers = new Map<BaseTabComponent, CompletionObserver>()
|
private completionObservers = new Map<BaseTabComponent, CompletionObserver>()
|
||||||
|
|
||||||
get activeTabChange$ (): Observable<BaseTabComponent> { return this.activeTabChange }
|
get activeTabChange$ (): Observable<BaseTabComponent|null> { return this.activeTabChange }
|
||||||
get tabOpened$ (): Observable<BaseTabComponent> { return this.tabOpened }
|
get tabOpened$ (): Observable<BaseTabComponent> { return this.tabOpened }
|
||||||
get tabsChanged$ (): Observable<void> { return this.tabsChanged }
|
get tabsChanged$ (): Observable<void> { return this.tabsChanged }
|
||||||
get tabClosed$ (): Observable<BaseTabComponent> { return this.tabClosed }
|
get tabClosed$ (): Observable<BaseTabComponent> { return this.tabClosed }
|
||||||
@@ -97,9 +97,7 @@ export class AppService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
hostApp.windowFocused$.subscribe(() => {
|
hostApp.windowFocused$.subscribe(() => this._activeTab?.emitFocused())
|
||||||
this._activeTab?.emitFocused()
|
|
||||||
})
|
|
||||||
|
|
||||||
this.tabClosed$.subscribe(async tab => {
|
this.tabClosed$.subscribe(async tab => {
|
||||||
const token = await tab.getRecoveryToken()
|
const token = await tab.getRecoveryToken()
|
||||||
@@ -187,12 +185,12 @@ export class AppService {
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
selectTab (tab: BaseTabComponent): void {
|
selectTab (tab: BaseTabComponent|null): void {
|
||||||
if (this._activeTab === tab) {
|
if (tab && this._activeTab === tab) {
|
||||||
this._activeTab.emitFocused()
|
this._activeTab.emitFocused()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (this.tabs.includes(this._activeTab)) {
|
if (this._activeTab && this.tabs.includes(this._activeTab)) {
|
||||||
this.lastTabIndex = this.tabs.indexOf(this._activeTab)
|
this.lastTabIndex = this.tabs.indexOf(this._activeTab)
|
||||||
} else {
|
} else {
|
||||||
this.lastTabIndex = 0
|
this.lastTabIndex = 0
|
||||||
@@ -203,12 +201,10 @@ export class AppService {
|
|||||||
}
|
}
|
||||||
this._activeTab = tab
|
this._activeTab = tab
|
||||||
this.activeTabChange.next(tab)
|
this.activeTabChange.next(tab)
|
||||||
if (this._activeTab) {
|
setImmediate(() => {
|
||||||
setImmediate(() => {
|
this._activeTab?.emitFocused()
|
||||||
this._activeTab.emitFocused()
|
})
|
||||||
})
|
this.hostApp.setTitle(this._activeTab?.title)
|
||||||
this.hostApp.setTitle(this._activeTab.title)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getParentTab (tab: BaseTabComponent): SplitTabComponent|null {
|
getParentTab (tab: BaseTabComponent): SplitTabComponent|null {
|
||||||
@@ -231,6 +227,9 @@ export class AppService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
nextTab (): void {
|
nextTab (): void {
|
||||||
|
if (!this._activeTab) {
|
||||||
|
return
|
||||||
|
}
|
||||||
if (this.tabs.length > 1) {
|
if (this.tabs.length > 1) {
|
||||||
const tabIndex = this.tabs.indexOf(this._activeTab)
|
const tabIndex = this.tabs.indexOf(this._activeTab)
|
||||||
if (tabIndex < this.tabs.length - 1) {
|
if (tabIndex < this.tabs.length - 1) {
|
||||||
@@ -242,6 +241,9 @@ export class AppService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
previousTab (): void {
|
previousTab (): void {
|
||||||
|
if (!this._activeTab) {
|
||||||
|
return
|
||||||
|
}
|
||||||
if (this.tabs.length > 1) {
|
if (this.tabs.length > 1) {
|
||||||
const tabIndex = this.tabs.indexOf(this._activeTab)
|
const tabIndex = this.tabs.indexOf(this._activeTab)
|
||||||
if (tabIndex > 0) {
|
if (tabIndex > 0) {
|
||||||
@@ -253,6 +255,9 @@ export class AppService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
moveSelectedTabLeft (): void {
|
moveSelectedTabLeft (): void {
|
||||||
|
if (!this._activeTab) {
|
||||||
|
return
|
||||||
|
}
|
||||||
if (this.tabs.length > 1) {
|
if (this.tabs.length > 1) {
|
||||||
const tabIndex = this.tabs.indexOf(this._activeTab)
|
const tabIndex = this.tabs.indexOf(this._activeTab)
|
||||||
if (tabIndex > 0) {
|
if (tabIndex > 0) {
|
||||||
@@ -264,6 +269,9 @@ export class AppService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
moveSelectedTabRight (): void {
|
moveSelectedTabRight (): void {
|
||||||
|
if (!this._activeTab) {
|
||||||
|
return
|
||||||
|
}
|
||||||
if (this.tabs.length > 1) {
|
if (this.tabs.length > 1) {
|
||||||
const tabIndex = this.tabs.indexOf(this._activeTab)
|
const tabIndex = this.tabs.indexOf(this._activeTab)
|
||||||
if (tabIndex < this.tabs.length - 1) {
|
if (tabIndex < this.tabs.length - 1) {
|
||||||
|
@@ -109,10 +109,7 @@ export class ConfigService {
|
|||||||
) {
|
) {
|
||||||
this.path = path.join(electron.app.getPath('userData'), 'config.yaml')
|
this.path = path.join(electron.app.getPath('userData'), 'config.yaml')
|
||||||
this.defaults = configProviders.map(provider => {
|
this.defaults = configProviders.map(provider => {
|
||||||
let defaults = {}
|
let defaults = provider.platformDefaults[hostApp.platform] || {}
|
||||||
if (provider.platformDefaults) {
|
|
||||||
defaults = configMerge(defaults, provider.platformDefaults[hostApp.platform] || {})
|
|
||||||
}
|
|
||||||
if (provider.defaults) {
|
if (provider.defaults) {
|
||||||
defaults = configMerge(defaults, provider.defaults)
|
defaults = configMerge(defaults, provider.defaults)
|
||||||
}
|
}
|
||||||
|
@@ -26,6 +26,7 @@ export class DockingService {
|
|||||||
|
|
||||||
let display = this.electron.screen.getAllDisplays()
|
let display = this.electron.screen.getAllDisplays()
|
||||||
.filter(x => x.id === this.config.store.appearance.dockScreen)[0]
|
.filter(x => x.id === this.config.store.appearance.dockScreen)[0]
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
||||||
if (!display) {
|
if (!display) {
|
||||||
display = this.getCurrentScreen()
|
display = this.getCurrentScreen()
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
import type { BrowserWindow, TouchBar, MenuItemConstructorOptions } from 'electron'
|
import type { BrowserWindow, TouchBar, MenuItemConstructorOptions } from 'electron'
|
||||||
import * as path from 'path'
|
import * as path from 'path'
|
||||||
|
import * as fs from 'mz/fs'
|
||||||
import shellEscape from 'shell-escape'
|
import shellEscape from 'shell-escape'
|
||||||
import { Observable, Subject } from 'rxjs'
|
import { Observable, Subject } from 'rxjs'
|
||||||
import { Injectable, NgZone, EventEmitter } from '@angular/core'
|
import { Injectable, NgZone, EventEmitter } from '@angular/core'
|
||||||
@@ -150,9 +151,10 @@ export class HostAppService {
|
|||||||
this.zone.run(() => this.displaysChanged.next())
|
this.zone.run(() => this.displaysChanged.next())
|
||||||
})
|
})
|
||||||
|
|
||||||
electron.ipcRenderer.on('host:second-instance', (_$event, argv: any, cwd: string) => this.zone.run(() => {
|
electron.ipcRenderer.on('cli', (_$event, argv: any, cwd: string, secondInstance: boolean) => this.zone.run(async () => {
|
||||||
this.logger.info('Second instance', argv)
|
this.logger.info('Second instance', argv)
|
||||||
const op = argv._[0]
|
const op = argv._[0]
|
||||||
|
const opAsPath = path.resolve(cwd, op)
|
||||||
if (op === 'open') {
|
if (op === 'open') {
|
||||||
this.cliOpenDirectory.next(path.resolve(cwd, argv.directory))
|
this.cliOpenDirectory.next(path.resolve(cwd, argv.directory))
|
||||||
} else if (op === 'run') {
|
} else if (op === 'run') {
|
||||||
@@ -167,7 +169,11 @@ export class HostAppService {
|
|||||||
this.cliOpenProfile.next(argv.profileName)
|
this.cliOpenProfile.next(argv.profileName)
|
||||||
} else if (op === undefined) {
|
} else if (op === undefined) {
|
||||||
this.newWindow()
|
this.newWindow()
|
||||||
} else {
|
} else if ((await fs.lstat(opAsPath)).isDirectory()) {
|
||||||
|
this.cliOpenDirectory.next(opAsPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (secondInstance) {
|
||||||
this.secondInstance.next()
|
this.secondInstance.next()
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
@@ -235,15 +241,15 @@ export class HostAppService {
|
|||||||
* @param type `null`, or `fluent` when supported (Windowd only)
|
* @param type `null`, or `fluent` when supported (Windowd only)
|
||||||
*/
|
*/
|
||||||
setVibrancy (enable: boolean, type: string|null): void {
|
setVibrancy (enable: boolean, type: string|null): void {
|
||||||
if (!isWindowsBuild(WIN_BUILD_FLUENT_BG_SUPPORTED)) {
|
if (this.platform === Platform.Windows && !isWindowsBuild(WIN_BUILD_FLUENT_BG_SUPPORTED)) {
|
||||||
type = null
|
type = null
|
||||||
}
|
}
|
||||||
document.body.classList.toggle('vibrant', enable)
|
document.body.classList.toggle('vibrant', enable)
|
||||||
this.electron.ipcRenderer.send('window-set-vibrancy', enable, type)
|
this.electron.ipcRenderer.send('window-set-vibrancy', enable, type)
|
||||||
}
|
}
|
||||||
|
|
||||||
setTitle (title: string): void {
|
setTitle (title?: string): void {
|
||||||
this.electron.ipcRenderer.send('window-set-title', title)
|
this.electron.ipcRenderer.send('window-set-title', title ?? 'Terminus')
|
||||||
}
|
}
|
||||||
|
|
||||||
setTouchBar (touchBar: TouchBar): void {
|
setTouchBar (touchBar: TouchBar): void {
|
||||||
|
@@ -172,7 +172,7 @@ export class HotkeysService {
|
|||||||
return (
|
return (
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
this.config.enabledServices(this.hotkeyProviders)
|
this.config.enabledServices(this.hotkeyProviders)
|
||||||
.map(async x => x.provide ? x.provide() : x.hotkeys)
|
.map(async x => x.provide())
|
||||||
)
|
)
|
||||||
).reduce((a, b) => a.concat(b))
|
).reduce((a, b) => a.concat(b))
|
||||||
}
|
}
|
||||||
@@ -222,7 +222,7 @@ export class HotkeysService {
|
|||||||
if (!(value instanceof Array)) {
|
if (!(value instanceof Array)) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if (value) {
|
if (value.length > 0) {
|
||||||
value = value.map((item: string | string[]) => typeof item === 'string' ? [item] : item)
|
value = value.map((item: string | string[]) => typeof item === 'string' ? [item] : item)
|
||||||
keys[key] = value
|
keys[key] = value
|
||||||
}
|
}
|
||||||
|
@@ -54,9 +54,7 @@ export class Logger {
|
|||||||
|
|
||||||
private doLog (level: string, ...args: any[]): void {
|
private doLog (level: string, ...args: any[]): void {
|
||||||
console[level](`%c[${this.name}]`, 'color: #aaa', ...args)
|
console[level](`%c[${this.name}]`, 'color: #aaa', ...args)
|
||||||
if (this.winstonLogger) {
|
this.winstonLogger[level](...args)
|
||||||
this.winstonLogger[level](...args)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -59,7 +59,7 @@ export class ShellIntegrationService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async install (): Promise<void> {
|
async install (): Promise<void> {
|
||||||
const exe: string = process.env.PORTABLE_EXECUTABLE_FILE || this.electron.app.getPath('exe')
|
const exe: string = process.env.PORTABLE_EXECUTABLE_FILE ?? this.electron.app.getPath('exe')
|
||||||
if (this.hostApp.platform === Platform.macOS) {
|
if (this.hostApp.platform === Platform.macOS) {
|
||||||
for (const wf of this.automatorWorkflows) {
|
for (const wf of this.automatorWorkflows) {
|
||||||
await exec(`cp -r "${this.automatorWorkflowsLocation}/${wf}" "${this.automatorWorkflowsDestination}"`)
|
await exec(`cp -r "${this.automatorWorkflowsLocation}/${wf}" "${this.automatorWorkflowsDestination}"`)
|
||||||
|
@@ -11,7 +11,7 @@ export class TabRecoveryService {
|
|||||||
enabled = false
|
enabled = false
|
||||||
|
|
||||||
private constructor (
|
private constructor (
|
||||||
@Inject(TabRecoveryProvider) private tabRecoveryProviders: TabRecoveryProvider[],
|
@Inject(TabRecoveryProvider) private tabRecoveryProviders: TabRecoveryProvider[]|null,
|
||||||
private config: ConfigService,
|
private config: ConfigService,
|
||||||
log: LogService
|
log: LogService
|
||||||
) {
|
) {
|
||||||
@@ -23,35 +23,28 @@ export class TabRecoveryService {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
window.localStorage.tabsRecovery = JSON.stringify(
|
window.localStorage.tabsRecovery = JSON.stringify(
|
||||||
await Promise.all(
|
(await Promise.all(
|
||||||
tabs
|
tabs
|
||||||
.map(tab => {
|
.map(async tab => tab.getRecoveryToken().then(r => {
|
||||||
let token = tab.getRecoveryToken()
|
if (r) {
|
||||||
if (token) {
|
r.tabTitle = tab.title
|
||||||
token = token.then(r => {
|
if (tab.color) {
|
||||||
if (r) {
|
r.tabColor = tab.color
|
||||||
r.tabTitle = tab.title
|
}
|
||||||
if (tab.color) {
|
|
||||||
r.tabColor = tab.color
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return r
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
return token
|
return r
|
||||||
})
|
}))
|
||||||
.filter(token => !!token)
|
)).filter(token => !!token)
|
||||||
)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
async recoverTab (token: RecoveryToken): Promise<RecoveredTab|null> {
|
async recoverTab (token: RecoveryToken): Promise<RecoveredTab|null> {
|
||||||
for (const provider of this.config.enabledServices(this.tabRecoveryProviders)) {
|
for (const provider of this.config.enabledServices(this.tabRecoveryProviders ?? [])) {
|
||||||
try {
|
try {
|
||||||
const tab = await provider.recover(token)
|
const tab = await provider.recover(token)
|
||||||
if (tab !== null) {
|
if (tab !== null) {
|
||||||
tab.options = tab.options || {}
|
tab.options = tab.options || {}
|
||||||
tab.options.color = token.tabColor || null
|
tab.options.color = token.tabColor ?? null
|
||||||
tab.options.title = token.tabTitle || ''
|
tab.options.title = token.tabTitle || ''
|
||||||
return tab
|
return tab
|
||||||
}
|
}
|
||||||
|
@@ -22,7 +22,7 @@ export class TabsService {
|
|||||||
const componentRef = componentFactory.create(this.injector)
|
const componentRef = componentFactory.create(this.injector)
|
||||||
const tab = componentRef.instance
|
const tab = componentRef.instance
|
||||||
tab.hostView = componentRef.hostView
|
tab.hostView = componentRef.hostView
|
||||||
Object.assign(tab, inputs || {})
|
Object.assign(tab, inputs ?? {})
|
||||||
return tab
|
return tab
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -18,11 +18,11 @@ export class ThemesService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
findTheme (name: string): Theme|null {
|
findTheme (name: string): Theme|null {
|
||||||
return this.config.enabledServices(this.themes).find(x => x.name === name) || null
|
return this.config.enabledServices(this.themes).find(x => x.name === name) ?? null
|
||||||
}
|
}
|
||||||
|
|
||||||
findCurrentTheme (): Theme {
|
findCurrentTheme (): Theme {
|
||||||
return this.findTheme(this.config.store.appearance.theme) || this.findTheme('Standard')!
|
return this.findTheme(this.config.store.appearance.theme) ?? this.findTheme('Standard')!
|
||||||
}
|
}
|
||||||
|
|
||||||
applyTheme (theme: Theme): void {
|
applyTheme (theme: Theme): void {
|
||||||
|
@@ -33,6 +33,7 @@ export class TouchbarService {
|
|||||||
app.tabOpened$.subscribe(tab => {
|
app.tabOpened$.subscribe(tab => {
|
||||||
tab.titleChange$.subscribe(title => {
|
tab.titleChange$.subscribe(title => {
|
||||||
const segment = this.tabSegments[app.tabs.indexOf(tab)]
|
const segment = this.tabSegments[app.tabs.indexOf(tab)]
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
||||||
if (segment) {
|
if (segment) {
|
||||||
segment.label = this.shortenTitle(title)
|
segment.label = this.shortenTitle(title)
|
||||||
this.tabsSegmentedControl.segments = this.tabSegments
|
this.tabsSegmentedControl.segments = this.tabSegments
|
||||||
@@ -41,6 +42,7 @@ export class TouchbarService {
|
|||||||
tab.activity$.subscribe(hasActivity => {
|
tab.activity$.subscribe(hasActivity => {
|
||||||
const showIcon = this.app.activeTab !== tab && hasActivity
|
const showIcon = this.app.activeTab !== tab && hasActivity
|
||||||
const segment = this.tabSegments[app.tabs.indexOf(tab)]
|
const segment = this.tabSegments[app.tabs.indexOf(tab)]
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
||||||
if (segment) {
|
if (segment) {
|
||||||
segment.icon = showIcon ? activityIcon : undefined
|
segment.icon = showIcon ? activityIcon : undefined
|
||||||
}
|
}
|
||||||
@@ -53,7 +55,7 @@ export class TouchbarService {
|
|||||||
label: this.shortenTitle(tab.title),
|
label: this.shortenTitle(tab.title),
|
||||||
}))
|
}))
|
||||||
this.tabsSegmentedControl.segments = this.tabSegments
|
this.tabsSegmentedControl.segments = this.tabSegments
|
||||||
this.tabsSegmentedControl.selectedIndex = this.app.tabs.indexOf(this.app.activeTab)
|
this.tabsSegmentedControl.selectedIndex = this.app.activeTab ? this.app.tabs.indexOf(this.app.activeTab) : 0
|
||||||
}
|
}
|
||||||
|
|
||||||
update (): void {
|
update (): void {
|
||||||
@@ -66,14 +68,14 @@ export class TouchbarService {
|
|||||||
buttons = buttons.concat(provider.provide())
|
buttons = buttons.concat(provider.provide())
|
||||||
})
|
})
|
||||||
buttons = buttons.filter(x => !!x.touchBarNSImage)
|
buttons = buttons.filter(x => !!x.touchBarNSImage)
|
||||||
buttons.sort((a, b) => (a.weight || 0) - (b.weight || 0))
|
buttons.sort((a, b) => (a.weight ?? 0) - (b.weight ?? 0))
|
||||||
this.tabSegments = this.app.tabs.map(tab => ({
|
this.tabSegments = this.app.tabs.map(tab => ({
|
||||||
label: this.shortenTitle(tab.title),
|
label: this.shortenTitle(tab.title),
|
||||||
}))
|
}))
|
||||||
|
|
||||||
this.tabsSegmentedControl = new this.electron.TouchBar.TouchBarSegmentedControl({
|
this.tabsSegmentedControl = new this.electron.TouchBar.TouchBarSegmentedControl({
|
||||||
segments: this.tabSegments,
|
segments: this.tabSegments,
|
||||||
selectedIndex: this.app.tabs.indexOf(this.app.activeTab),
|
selectedIndex: this.app.activeTab ? this.app.tabs.indexOf(this.app.activeTab) : undefined,
|
||||||
change: (selectedIndex) => this.zone.run(() => {
|
change: (selectedIndex) => this.zone.run(() => {
|
||||||
this.app.selectTab(this.app.tabs[selectedIndex])
|
this.app.selectTab(this.app.tabs[selectedIndex])
|
||||||
}),
|
}),
|
||||||
@@ -102,13 +104,14 @@ export class TouchbarService {
|
|||||||
|
|
||||||
private getButton (button: ToolbarButton): SegmentedControlSegment {
|
private getButton (button: ToolbarButton): SegmentedControlSegment {
|
||||||
return {
|
return {
|
||||||
label: button.touchBarNSImage ? undefined : this.shortenTitle(button.touchBarTitle || button.title),
|
label: button.touchBarNSImage ? undefined : this.shortenTitle(button.touchBarTitle ?? button.title),
|
||||||
icon: button.touchBarNSImage ? this.getCachedNSImage(button.touchBarNSImage) : undefined,
|
icon: button.touchBarNSImage ? this.getCachedNSImage(button.touchBarNSImage) : undefined,
|
||||||
// click: () => this.zone.run(() => button.click()),
|
// click: () => this.zone.run(() => button.click()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private getCachedNSImage (name: string) {
|
private getCachedNSImage (name: string) {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
||||||
if (!this.nsImageCache[name]) {
|
if (!this.nsImageCache[name]) {
|
||||||
this.nsImageCache[name] = this.electron.nativeImage.createFromNamedImage(name, [0, 0, 1])
|
this.nsImageCache[name] = this.electron.nativeImage.createFromNamedImage(name, [0, 0, 1])
|
||||||
}
|
}
|
||||||
|
@@ -35,6 +35,10 @@ export class UpdaterService {
|
|||||||
this.logger.info('No updates')
|
this.logger.info('No updates')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
electron.autoUpdater.once('error', err => {
|
||||||
|
this.logger.error(err)
|
||||||
|
})
|
||||||
|
|
||||||
this.downloaded = new Promise<boolean>(resolve => {
|
this.downloaded = new Promise<boolean>(resolve => {
|
||||||
electron.autoUpdater.once('update-downloaded', () => resolve(true))
|
electron.autoUpdater.once('update-downloaded', () => resolve(true))
|
||||||
})
|
})
|
||||||
|
@@ -113,7 +113,7 @@ export class CommonOptionsContextMenu extends TabContextMenuItemProvider {
|
|||||||
...items,
|
...items,
|
||||||
{
|
{
|
||||||
label: 'Rename',
|
label: 'Rename',
|
||||||
click: () => this.zone.run(() => tabHeader?.showRenameTabModal()),
|
click: () => this.zone.run(() => tabHeader.showRenameTabModal()),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Duplicate',
|
label: 'Duplicate',
|
||||||
|
@@ -124,9 +124,9 @@ colorspace@1.1.x:
|
|||||||
text-hex "1.0.x"
|
text-hex "1.0.x"
|
||||||
|
|
||||||
core-js@^3.1.2:
|
core-js@^3.1.2:
|
||||||
version "3.7.0"
|
version "3.8.2"
|
||||||
resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.7.0.tgz#b0a761a02488577afbf97179e4681bf49568520f"
|
resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.8.2.tgz#0a1fd6709246da9ca8eff5bb0cbd15fba9ac7044"
|
||||||
integrity sha512-NwS7fI5M5B85EwpWuIwJN4i/fbisQUwLwiSNUWeXlkAZ0sbBjLEvLvFLf1uzAUV66PcEPt4xCGCmOZSxVf3xzA==
|
integrity sha512-FfApuSRgrR6G5s58casCBd9M2k+4ikuu4wbW6pJyYU7bd9zvFc9qf7vr5xmrZOhT9nn+8uwlH1oRR9jTnFoA3A==
|
||||||
|
|
||||||
core-util-is@~1.0.0:
|
core-util-is@~1.0.0:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
|
@@ -19,6 +19,7 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/semver": "^7.1.0",
|
"@types/semver": "^7.1.0",
|
||||||
"axios": "^0.19.0",
|
"axios": "^0.19.0",
|
||||||
|
"electron-promise-ipc": "^2.2.4",
|
||||||
"mz": "^2.6.0",
|
"mz": "^2.6.0",
|
||||||
"semver": "^7.1.1"
|
"semver": "^7.1.1"
|
||||||
},
|
},
|
||||||
|
@@ -22,10 +22,10 @@
|
|||||||
button.btn.btn-primary.ml-2(
|
button.btn.btn-primary.ml-2(
|
||||||
*ngIf='knownUpgrades[plugin.name]',
|
*ngIf='knownUpgrades[plugin.name]',
|
||||||
(click)='upgradePlugin(plugin)',
|
(click)='upgradePlugin(plugin)',
|
||||||
[disabled]='busy[plugin.name] != undefined'
|
[disabled]='busy.has(plugin.name)'
|
||||||
)
|
)
|
||||||
i.fas.fa-fw.fa-arrow-up(*ngIf='busy[plugin.name] != BusyState.Installing')
|
i.fas.fa-fw.fa-arrow-up(*ngIf='busy.get(plugin.name) != BusyState.Installing')
|
||||||
i.fas.fa-fw.fa-circle-notch.fa-spin(*ngIf='busy[plugin.name] == BusyState.Installing')
|
i.fas.fa-fw.fa-circle-notch.fa-spin(*ngIf='busy.get(plugin.name) == BusyState.Installing')
|
||||||
span Upgrade ({{knownUpgrades[plugin.name].version}})
|
span Upgrade ({{knownUpgrades[plugin.name].version}})
|
||||||
|
|
||||||
button.btn.btn-link.text-primary.ml-2(
|
button.btn.btn-link.text-primary.ml-2(
|
||||||
@@ -43,10 +43,10 @@
|
|||||||
button.btn.btn-link.text-danger.ml-2(
|
button.btn.btn-link.text-danger.ml-2(
|
||||||
(click)='uninstallPlugin(plugin)',
|
(click)='uninstallPlugin(plugin)',
|
||||||
*ngIf='!plugin.isBuiltin',
|
*ngIf='!plugin.isBuiltin',
|
||||||
[disabled]='busy[plugin.name] != undefined'
|
[disabled]='busy.has(plugin.name)'
|
||||||
)
|
)
|
||||||
i.fas.fa-fw.fa-trash(*ngIf='busy[plugin.name] != BusyState.Uninstalling')
|
i.fas.fa-fw.fa-trash(*ngIf='busy.get(plugin.name) != BusyState.Uninstalling')
|
||||||
i.fas.fa-fw.fa-circle-notch.fa-spin(*ngIf='busy[plugin.name] == BusyState.Uninstalling')
|
i.fas.fa-fw.fa-circle-notch.fa-spin(*ngIf='busy.get(plugin.name) == BusyState.Uninstalling')
|
||||||
|
|
||||||
div
|
div
|
||||||
h3.mt-4 Available
|
h3.mt-4 Available
|
||||||
@@ -69,10 +69,10 @@ div
|
|||||||
.list-group-item.d-flex.align-items-center(*ngIf='!isAlreadyInstalled(plugin)')
|
.list-group-item.d-flex.align-items-center(*ngIf='!isAlreadyInstalled(plugin)')
|
||||||
button.btn.btn-primary.mr-3(
|
button.btn.btn-primary.mr-3(
|
||||||
(click)='installPlugin(plugin)',
|
(click)='installPlugin(plugin)',
|
||||||
[disabled]='busy[plugin.name] != undefined'
|
[disabled]='busy.has(plugin.name)'
|
||||||
)
|
)
|
||||||
i.fas.fa-fw.fa-download(*ngIf='busy[plugin.name] != BusyState.Installing')
|
i.fas.fa-fw.fa-download(*ngIf='busy.get(plugin.name) != BusyState.Installing')
|
||||||
i.fas.fa-fw.fa-circle-notch.fa-spin(*ngIf='busy[plugin.name] == BusyState.Installing')
|
i.fas.fa-fw.fa-circle-notch.fa-spin(*ngIf='busy.get(plugin.name) == BusyState.Installing')
|
||||||
|
|
||||||
div((click)='showPluginInfo(plugin)')
|
div((click)='showPluginInfo(plugin)')
|
||||||
div
|
div
|
||||||
|
@@ -20,7 +20,7 @@ export class PluginsSettingsTabComponent {
|
|||||||
@Input() availablePluginsQuery$ = new BehaviorSubject<string>('')
|
@Input() availablePluginsQuery$ = new BehaviorSubject<string>('')
|
||||||
@Input() availablePluginsReady = false
|
@Input() availablePluginsReady = false
|
||||||
@Input() knownUpgrades: Record<string, PluginInfo|null> = {}
|
@Input() knownUpgrades: Record<string, PluginInfo|null> = {}
|
||||||
@Input() busy: Record<string, BusyState> = {}
|
@Input() busy = new Map<string, BusyState>()
|
||||||
@Input() erroredPlugin: string
|
@Input() erroredPlugin: string
|
||||||
@Input() errorMessage: string
|
@Input() errorMessage: string
|
||||||
|
|
||||||
@@ -67,29 +67,29 @@ export class PluginsSettingsTabComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async installPlugin (plugin: PluginInfo): Promise<void> {
|
async installPlugin (plugin: PluginInfo): Promise<void> {
|
||||||
this.busy[plugin.name] = BusyState.Installing
|
this.busy.set(plugin.name, BusyState.Installing)
|
||||||
try {
|
try {
|
||||||
await this.pluginManager.installPlugin(plugin)
|
await this.pluginManager.installPlugin(plugin)
|
||||||
delete this.busy[plugin.name]
|
this.busy.delete(plugin.name)
|
||||||
this.config.requestRestart()
|
this.config.requestRestart()
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
this.erroredPlugin = plugin.name
|
this.erroredPlugin = plugin.name
|
||||||
this.errorMessage = err
|
this.errorMessage = err
|
||||||
delete this.busy[plugin.name]
|
this.busy.delete(plugin.name)
|
||||||
throw err
|
throw err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async uninstallPlugin (plugin: PluginInfo): Promise<void> {
|
async uninstallPlugin (plugin: PluginInfo): Promise<void> {
|
||||||
this.busy[plugin.name] = BusyState.Uninstalling
|
this.busy.set(plugin.name, BusyState.Uninstalling)
|
||||||
try {
|
try {
|
||||||
await this.pluginManager.uninstallPlugin(plugin)
|
await this.pluginManager.uninstallPlugin(plugin)
|
||||||
delete this.busy[plugin.name]
|
this.busy.delete(plugin.name)
|
||||||
this.config.requestRestart()
|
this.config.requestRestart()
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
this.erroredPlugin = plugin.name
|
this.erroredPlugin = plugin.name
|
||||||
this.errorMessage = err
|
this.errorMessage = err
|
||||||
delete this.busy[plugin.name]
|
this.busy.delete(plugin.name)
|
||||||
throw err
|
throw err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
|
import promiseIpc from 'electron-promise-ipc'
|
||||||
import { Observable, from } from 'rxjs'
|
import { Observable, from } from 'rxjs'
|
||||||
import { map } from 'rxjs/operators'
|
import { map } from 'rxjs/operators'
|
||||||
import { Injectable } from '@angular/core'
|
import { Injectable } from '@angular/core'
|
||||||
@@ -31,39 +32,15 @@ export class PluginManagerService {
|
|||||||
userPluginsPath: string = (window as any).userPluginsPath
|
userPluginsPath: string = (window as any).userPluginsPath
|
||||||
installedPlugins: PluginInfo[] = (window as any).installedPlugins
|
installedPlugins: PluginInfo[] = (window as any).installedPlugins
|
||||||
|
|
||||||
private npmReady: Promise<void>
|
|
||||||
private npm: any
|
|
||||||
|
|
||||||
private constructor (
|
private constructor (
|
||||||
log: LogService,
|
log: LogService,
|
||||||
) {
|
) {
|
||||||
this.logger = log.create('pluginManager')
|
this.logger = log.create('pluginManager')
|
||||||
}
|
}
|
||||||
|
|
||||||
async getNPM (): Promise<any> {
|
|
||||||
if (!this.npm) {
|
|
||||||
if (!this.npmReady) {
|
|
||||||
this.npmReady = new Promise(resolve => {
|
|
||||||
const npm = (global as any).require('npm')
|
|
||||||
npm.load({
|
|
||||||
prefix: this.userPluginsPath,
|
|
||||||
}, err => {
|
|
||||||
if (err) {
|
|
||||||
this.logger.error(err)
|
|
||||||
}
|
|
||||||
this.npm = npm
|
|
||||||
resolve()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
await this.npmReady
|
|
||||||
}
|
|
||||||
return this.npm
|
|
||||||
}
|
|
||||||
|
|
||||||
listAvailable (query?: string): Observable<PluginInfo[]> {
|
listAvailable (query?: string): Observable<PluginInfo[]> {
|
||||||
return from(
|
return from(
|
||||||
axios.get(`https://www.npmjs.com/search?q=keywords%3A${KEYWORD}+${encodeURIComponent(query || '')}&from=0&size=1000`, {
|
axios.get(`https://www.npmjs.com/search?q=keywords%3A${KEYWORD}+${encodeURIComponent(query ?? '')}&from=0&size=1000`, {
|
||||||
headers: {
|
headers: {
|
||||||
'x-spiferack': '1',
|
'x-spiferack': '1',
|
||||||
},
|
},
|
||||||
@@ -84,21 +61,23 @@ export class PluginManagerService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async installPlugin (plugin: PluginInfo): Promise<void> {
|
async installPlugin (plugin: PluginInfo): Promise<void> {
|
||||||
(await this.getNPM()).commands.install([`${plugin.packageName}@${plugin.version}`], err => {
|
try {
|
||||||
if (err) {
|
await (promiseIpc as any).send('plugin-manager:install', this.userPluginsPath, plugin.packageName, plugin.version)
|
||||||
this.logger.error(err)
|
|
||||||
}
|
|
||||||
this.installedPlugins = this.installedPlugins.filter(x => x.packageName !== plugin.packageName)
|
this.installedPlugins = this.installedPlugins.filter(x => x.packageName !== plugin.packageName)
|
||||||
this.installedPlugins.push(plugin)
|
this.installedPlugins.push(plugin)
|
||||||
})
|
} catch (err) {
|
||||||
|
this.logger.error(err)
|
||||||
|
throw err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async uninstallPlugin (plugin: PluginInfo): Promise<void> {
|
async uninstallPlugin (plugin: PluginInfo): Promise<void> {
|
||||||
(await this.getNPM()).commands.remove([plugin.packageName], err => {
|
try {
|
||||||
if (err) {
|
await (promiseIpc as any).send('plugin-manager:uninstall', this.userPluginsPath, plugin.packageName)
|
||||||
this.logger.error(err)
|
|
||||||
}
|
|
||||||
this.installedPlugins = this.installedPlugins.filter(x => x.packageName !== plugin.packageName)
|
this.installedPlugins = this.installedPlugins.filter(x => x.packageName !== plugin.packageName)
|
||||||
})
|
} catch (err) {
|
||||||
|
this.logger.error(err)
|
||||||
|
throw err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -46,8 +46,8 @@ module.exports = {
|
|||||||
externals: [
|
externals: [
|
||||||
'fs',
|
'fs',
|
||||||
'net',
|
'net',
|
||||||
'npm',
|
|
||||||
'path',
|
'path',
|
||||||
|
'electron-promise-ipc',
|
||||||
/^rxjs/,
|
/^rxjs/,
|
||||||
/^@angular/,
|
/^@angular/,
|
||||||
/^@ng-bootstrap/,
|
/^@ng-bootstrap/,
|
||||||
|
@@ -19,6 +19,14 @@ axios@^0.19.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
follow-redirects "1.5.10"
|
follow-redirects "1.5.10"
|
||||||
|
|
||||||
|
call-bind@^1.0.0:
|
||||||
|
version "1.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.0.tgz#24127054bb3f9bdcb4b1fb82418186072f77b8ce"
|
||||||
|
integrity sha512-AEXsYIyyDY3MCzbwdhzG3Jx1R0J2wetQyUynn6dYHAO+bg8l1k7jwZtRv4ryryFs7EP+NDlikJlVe59jr0cM2w==
|
||||||
|
dependencies:
|
||||||
|
function-bind "^1.1.1"
|
||||||
|
get-intrinsic "^1.0.0"
|
||||||
|
|
||||||
debug@=3.1.0:
|
debug@=3.1.0:
|
||||||
version "3.1.0"
|
version "3.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
|
resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
|
||||||
@@ -26,6 +34,50 @@ debug@=3.1.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
ms "2.0.0"
|
ms "2.0.0"
|
||||||
|
|
||||||
|
define-properties@^1.1.3:
|
||||||
|
version "1.1.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1"
|
||||||
|
integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==
|
||||||
|
dependencies:
|
||||||
|
object-keys "^1.0.12"
|
||||||
|
|
||||||
|
electron-promise-ipc@^2.2.4:
|
||||||
|
version "2.2.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/electron-promise-ipc/-/electron-promise-ipc-2.2.4.tgz#b82daf86ca6d0f0b8655937fdbe9a554590deeea"
|
||||||
|
integrity sha512-xCkFEeuru9l7H/+m1gpK4F1utexvTT7+n1PTquP2MVTpmBmpgFBlLqSXC7TqwpROkHRm9wGpaCJEx0djonnSEg==
|
||||||
|
dependencies:
|
||||||
|
is-electron-renderer "^2.0.1"
|
||||||
|
object.entries "^1.1.3"
|
||||||
|
serialize-error "^5.0.0"
|
||||||
|
uuid "^3.0.1"
|
||||||
|
|
||||||
|
es-abstract@^1.18.0-next.1:
|
||||||
|
version "1.18.0-next.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.18.0-next.1.tgz#6e3a0a4bda717e5023ab3b8e90bec36108d22c68"
|
||||||
|
integrity sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==
|
||||||
|
dependencies:
|
||||||
|
es-to-primitive "^1.2.1"
|
||||||
|
function-bind "^1.1.1"
|
||||||
|
has "^1.0.3"
|
||||||
|
has-symbols "^1.0.1"
|
||||||
|
is-callable "^1.2.2"
|
||||||
|
is-negative-zero "^2.0.0"
|
||||||
|
is-regex "^1.1.1"
|
||||||
|
object-inspect "^1.8.0"
|
||||||
|
object-keys "^1.1.1"
|
||||||
|
object.assign "^4.1.1"
|
||||||
|
string.prototype.trimend "^1.0.1"
|
||||||
|
string.prototype.trimstart "^1.0.1"
|
||||||
|
|
||||||
|
es-to-primitive@^1.2.1:
|
||||||
|
version "1.2.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a"
|
||||||
|
integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==
|
||||||
|
dependencies:
|
||||||
|
is-callable "^1.1.4"
|
||||||
|
is-date-object "^1.0.1"
|
||||||
|
is-symbol "^1.0.2"
|
||||||
|
|
||||||
follow-redirects@1.5.10:
|
follow-redirects@1.5.10:
|
||||||
version "1.5.10"
|
version "1.5.10"
|
||||||
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.5.10.tgz#7b7a9f9aea2fdff36786a94ff643ed07f4ff5e2a"
|
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.5.10.tgz#7b7a9f9aea2fdff36786a94ff643ed07f4ff5e2a"
|
||||||
@@ -33,6 +85,66 @@ follow-redirects@1.5.10:
|
|||||||
dependencies:
|
dependencies:
|
||||||
debug "=3.1.0"
|
debug "=3.1.0"
|
||||||
|
|
||||||
|
function-bind@^1.1.1:
|
||||||
|
version "1.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
|
||||||
|
integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==
|
||||||
|
|
||||||
|
get-intrinsic@^1.0.0:
|
||||||
|
version "1.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.0.2.tgz#6820da226e50b24894e08859469dc68361545d49"
|
||||||
|
integrity sha512-aeX0vrFm21ILl3+JpFFRNe9aUvp6VFZb2/CTbgLb8j75kOhvoNYjt9d8KA/tJG4gSo8nzEDedRl0h7vDmBYRVg==
|
||||||
|
dependencies:
|
||||||
|
function-bind "^1.1.1"
|
||||||
|
has "^1.0.3"
|
||||||
|
has-symbols "^1.0.1"
|
||||||
|
|
||||||
|
has-symbols@^1.0.1:
|
||||||
|
version "1.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8"
|
||||||
|
integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==
|
||||||
|
|
||||||
|
has@^1.0.3:
|
||||||
|
version "1.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796"
|
||||||
|
integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==
|
||||||
|
dependencies:
|
||||||
|
function-bind "^1.1.1"
|
||||||
|
|
||||||
|
is-callable@^1.1.4, is-callable@^1.2.2:
|
||||||
|
version "1.2.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.2.tgz#c7c6715cd22d4ddb48d3e19970223aceabb080d9"
|
||||||
|
integrity sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA==
|
||||||
|
|
||||||
|
is-date-object@^1.0.1:
|
||||||
|
version "1.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.2.tgz#bda736f2cd8fd06d32844e7743bfa7494c3bfd7e"
|
||||||
|
integrity sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==
|
||||||
|
|
||||||
|
is-electron-renderer@^2.0.1:
|
||||||
|
version "2.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/is-electron-renderer/-/is-electron-renderer-2.0.1.tgz#a469d056f975697c58c98c6023eb0aa79af895a2"
|
||||||
|
integrity sha1-pGnQVvl1aXxYyYxgI+sKp5r4laI=
|
||||||
|
|
||||||
|
is-negative-zero@^2.0.0:
|
||||||
|
version "2.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.1.tgz#3de746c18dda2319241a53675908d8f766f11c24"
|
||||||
|
integrity sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==
|
||||||
|
|
||||||
|
is-regex@^1.1.1:
|
||||||
|
version "1.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.1.tgz#c6f98aacc546f6cec5468a07b7b153ab564a57b9"
|
||||||
|
integrity sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==
|
||||||
|
dependencies:
|
||||||
|
has-symbols "^1.0.1"
|
||||||
|
|
||||||
|
is-symbol@^1.0.2:
|
||||||
|
version "1.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.3.tgz#38e1014b9e6329be0de9d24a414fd7441ec61937"
|
||||||
|
integrity sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==
|
||||||
|
dependencies:
|
||||||
|
has-symbols "^1.0.1"
|
||||||
|
|
||||||
ms@2.0.0:
|
ms@2.0.0:
|
||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
|
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
|
||||||
@@ -52,11 +164,64 @@ object-assign@^4.0.1:
|
|||||||
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
|
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
|
||||||
integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=
|
integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=
|
||||||
|
|
||||||
|
object-inspect@^1.8.0:
|
||||||
|
version "1.9.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.9.0.tgz#c90521d74e1127b67266ded3394ad6116986533a"
|
||||||
|
integrity sha512-i3Bp9iTqwhaLZBxGkRfo5ZbE07BQRT7MGu8+nNgwW9ItGp1TzCTw2DLEoWwjClxBjOFI/hWljTAmYGCEwmtnOw==
|
||||||
|
|
||||||
|
object-keys@^1.0.12, object-keys@^1.1.1:
|
||||||
|
version "1.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e"
|
||||||
|
integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==
|
||||||
|
|
||||||
|
object.assign@^4.1.1:
|
||||||
|
version "4.1.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.2.tgz#0ed54a342eceb37b38ff76eb831a0e788cb63940"
|
||||||
|
integrity sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==
|
||||||
|
dependencies:
|
||||||
|
call-bind "^1.0.0"
|
||||||
|
define-properties "^1.1.3"
|
||||||
|
has-symbols "^1.0.1"
|
||||||
|
object-keys "^1.1.1"
|
||||||
|
|
||||||
|
object.entries@^1.1.3:
|
||||||
|
version "1.1.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.3.tgz#c601c7f168b62374541a07ddbd3e2d5e4f7711a6"
|
||||||
|
integrity sha512-ym7h7OZebNS96hn5IJeyUmaWhaSM4SVtAPPfNLQEI2MYWCO2egsITb9nab2+i/Pwibx+R0mtn+ltKJXRSeTMGg==
|
||||||
|
dependencies:
|
||||||
|
call-bind "^1.0.0"
|
||||||
|
define-properties "^1.1.3"
|
||||||
|
es-abstract "^1.18.0-next.1"
|
||||||
|
has "^1.0.3"
|
||||||
|
|
||||||
semver@^7.1.1:
|
semver@^7.1.1:
|
||||||
version "7.3.2"
|
version "7.3.2"
|
||||||
resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.2.tgz#604962b052b81ed0786aae84389ffba70ffd3938"
|
resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.2.tgz#604962b052b81ed0786aae84389ffba70ffd3938"
|
||||||
integrity sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==
|
integrity sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==
|
||||||
|
|
||||||
|
serialize-error@^5.0.0:
|
||||||
|
version "5.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/serialize-error/-/serialize-error-5.0.0.tgz#a7ebbcdb03a5d71a6ed8461ffe0fc1a1afed62ac"
|
||||||
|
integrity sha512-/VtpuyzYf82mHYTtI4QKtwHa79vAdU5OQpNPAmE/0UDdlGT0ZxHwC+J6gXkw29wwoVI8fMPsfcVHOwXtUQYYQA==
|
||||||
|
dependencies:
|
||||||
|
type-fest "^0.8.0"
|
||||||
|
|
||||||
|
string.prototype.trimend@^1.0.1:
|
||||||
|
version "1.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.3.tgz#a22bd53cca5c7cf44d7c9d5c732118873d6cd18b"
|
||||||
|
integrity sha512-ayH0pB+uf0U28CtjlLvL7NaohvR1amUvVZk+y3DYb0Ey2PUV5zPkkKy9+U1ndVEIXO8hNg18eIv9Jntbii+dKw==
|
||||||
|
dependencies:
|
||||||
|
call-bind "^1.0.0"
|
||||||
|
define-properties "^1.1.3"
|
||||||
|
|
||||||
|
string.prototype.trimstart@^1.0.1:
|
||||||
|
version "1.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.3.tgz#9b4cb590e123bb36564401d59824298de50fd5aa"
|
||||||
|
integrity sha512-oBIBUy5lea5tt0ovtOFiEQaBkoBBkyJhZXzJYrSmDo5IUUqbOPvVezuRs/agBIdZ2p2Eo1FD6bD9USyBLfl3xg==
|
||||||
|
dependencies:
|
||||||
|
call-bind "^1.0.0"
|
||||||
|
define-properties "^1.1.3"
|
||||||
|
|
||||||
thenify-all@^1.0.0:
|
thenify-all@^1.0.0:
|
||||||
version "1.6.0"
|
version "1.6.0"
|
||||||
resolved "https://registry.yarnpkg.com/thenify-all/-/thenify-all-1.6.0.tgz#1a1918d402d8fc3f98fbf234db0bcc8cc10e9726"
|
resolved "https://registry.yarnpkg.com/thenify-all/-/thenify-all-1.6.0.tgz#1a1918d402d8fc3f98fbf234db0bcc8cc10e9726"
|
||||||
@@ -70,3 +235,13 @@ thenify-all@^1.0.0:
|
|||||||
integrity sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==
|
integrity sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==
|
||||||
dependencies:
|
dependencies:
|
||||||
any-promise "^1.0.0"
|
any-promise "^1.0.0"
|
||||||
|
|
||||||
|
type-fest@^0.8.0:
|
||||||
|
version "0.8.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d"
|
||||||
|
integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==
|
||||||
|
|
||||||
|
uuid@^3.0.1:
|
||||||
|
version "3.4.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee"
|
||||||
|
integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==
|
||||||
|
@@ -26,7 +26,7 @@ export interface SerialConnection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const BAUD_RATES = [
|
export const BAUD_RATES = [
|
||||||
110, 150, 300, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600,
|
110, 150, 300, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600, 1500000,
|
||||||
]
|
]
|
||||||
|
|
||||||
export interface SerialPortInfo {
|
export interface SerialPortInfo {
|
||||||
@@ -44,7 +44,7 @@ export class SerialSession extends BaseSession {
|
|||||||
|
|
||||||
constructor (public connection: SerialConnection) {
|
constructor (public connection: SerialConnection) {
|
||||||
super()
|
super()
|
||||||
this.scripts = connection.scripts || []
|
this.scripts = connection.scripts ?? []
|
||||||
}
|
}
|
||||||
|
|
||||||
async start (): Promise<void> {
|
async start (): Promise<void> {
|
||||||
@@ -131,6 +131,10 @@ export class SerialSession extends BaseSession {
|
|||||||
this.kill('TERM')
|
this.kill('TERM')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
supportsWorkingDirectory (): boolean {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
async getWorkingDirectory (): Promise<string|null> {
|
async getWorkingDirectory (): Promise<string|null> {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
@@ -28,7 +28,7 @@ export class ButtonProvider extends ToolbarButtonProvider {
|
|||||||
weight: 5,
|
weight: 5,
|
||||||
title: 'Serial connections',
|
title: 'Serial connections',
|
||||||
touchBarNSImage: 'NSTouchBarOpenInBrowserTemplate',
|
touchBarNSImage: 'NSTouchBarOpenInBrowserTemplate',
|
||||||
click: async () => {
|
click: () => {
|
||||||
this.activate()
|
this.activate()
|
||||||
},
|
},
|
||||||
}]
|
}]
|
||||||
|
@@ -37,7 +37,7 @@ export class EditConnectionModalComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async ngOnInit () {
|
async ngOnInit () {
|
||||||
this.connection.scripts = this.connection.scripts || []
|
this.connection.scripts = this.connection.scripts ?? []
|
||||||
this.foundPorts = await this.serial.listPorts()
|
this.foundPorts = await this.serial.listPorts()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -16,8 +16,8 @@ import { Subscription } from 'rxjs'
|
|||||||
animations: BaseTerminalTabComponent.animations,
|
animations: BaseTerminalTabComponent.animations,
|
||||||
})
|
})
|
||||||
export class SerialTabComponent extends BaseTerminalTabComponent {
|
export class SerialTabComponent extends BaseTerminalTabComponent {
|
||||||
connection: SerialConnection
|
connection?: SerialConnection
|
||||||
session: SerialSession
|
session?: SerialSession
|
||||||
serialPort: any
|
serialPort: any
|
||||||
private homeEndSubscription: Subscription
|
private homeEndSubscription: Subscription
|
||||||
|
|
||||||
@@ -52,7 +52,7 @@ export class SerialTabComponent extends BaseTerminalTabComponent {
|
|||||||
super.ngOnInit()
|
super.ngOnInit()
|
||||||
|
|
||||||
setImmediate(() => {
|
setImmediate(() => {
|
||||||
this.setTitle(this.connection.name)
|
this.setTitle(this.connection!.name)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,7 +65,7 @@ export class SerialTabComponent extends BaseTerminalTabComponent {
|
|||||||
this.session = this.injector.get(SerialService).createSession(this.connection)
|
this.session = this.injector.get(SerialService).createSession(this.connection)
|
||||||
this.session.serviceMessage$.subscribe(msg => {
|
this.session.serviceMessage$.subscribe(msg => {
|
||||||
this.write(`\r\n${colors.black.bgWhite(' serial ')} ${msg}\r\n`)
|
this.write(`\r\n${colors.black.bgWhite(' serial ')} ${msg}\r\n`)
|
||||||
this.session.resize(this.size.columns, this.size.rows)
|
this.session?.resize(this.size.columns, this.size.rows)
|
||||||
})
|
})
|
||||||
this.attachSessionHandlers()
|
this.attachSessionHandlers()
|
||||||
this.write(`Connecting to `)
|
this.write(`Connecting to `)
|
||||||
@@ -108,7 +108,7 @@ export class SerialTabComponent extends BaseTerminalTabComponent {
|
|||||||
name: x.toString(), result: x,
|
name: x.toString(), result: x,
|
||||||
})))
|
})))
|
||||||
this.serialPort.update({ baudRate: rate })
|
this.serialPort.update({ baudRate: rate })
|
||||||
this.connection.baudrate = rate
|
this.connection!.baudrate = rate
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnDestroy () {
|
ngOnDestroy () {
|
||||||
|
@@ -7,7 +7,7 @@ import { SerialTabComponent } from './components/serialTab.component'
|
|||||||
@Injectable()
|
@Injectable()
|
||||||
export class RecoveryProvider extends TabRecoveryProvider {
|
export class RecoveryProvider extends TabRecoveryProvider {
|
||||||
async recover (recoveryToken: RecoveryToken): Promise<RecoveredTab|null> {
|
async recover (recoveryToken: RecoveryToken): Promise<RecoveredTab|null> {
|
||||||
if (recoveryToken?.type === 'app:serial-tab') {
|
if (recoveryToken.type === 'app:serial-tab') {
|
||||||
return {
|
return {
|
||||||
type: SerialTabComponent,
|
type: SerialTabComponent,
|
||||||
options: {
|
options: {
|
||||||
|
@@ -57,7 +57,6 @@ export class SerialService {
|
|||||||
this.toastr.error(e.message)
|
this.toastr.error(e.message)
|
||||||
reject(e)
|
reject(e)
|
||||||
}
|
}
|
||||||
|
|
||||||
})
|
})
|
||||||
return serial
|
return serial
|
||||||
}
|
}
|
||||||
@@ -125,10 +124,10 @@ export class SerialService {
|
|||||||
{ connection }
|
{ connection }
|
||||||
) as SerialTabComponent
|
) as SerialTabComponent
|
||||||
if (connection.color) {
|
if (connection.color) {
|
||||||
(this.app.getParentTab(tab) || tab).color = connection.color
|
(this.app.getParentTab(tab) ?? tab).color = connection.color
|
||||||
}
|
}
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.app.activeTab.emitFocused()
|
this.app.activeTab?.emitFocused()
|
||||||
})
|
})
|
||||||
return tab
|
return tab
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
@@ -10,7 +10,7 @@ import { HotkeyInputModalComponent } from './hotkeyInputModal.component'
|
|||||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
})
|
})
|
||||||
export class MultiHotkeyInputComponent {
|
export class MultiHotkeyInputComponent {
|
||||||
@Input() model: string[][]
|
@Input() model: string[][] = []
|
||||||
@Output() modelChange = new EventEmitter()
|
@Output() modelChange = new EventEmitter()
|
||||||
|
|
||||||
constructor (
|
constructor (
|
||||||
@@ -18,9 +18,6 @@ export class MultiHotkeyInputComponent {
|
|||||||
) { }
|
) { }
|
||||||
|
|
||||||
ngOnInit (): void {
|
ngOnInit (): void {
|
||||||
if (!this.model) {
|
|
||||||
this.model = []
|
|
||||||
}
|
|
||||||
if (typeof this.model === 'string') {
|
if (typeof this.model === 'string') {
|
||||||
this.model = [this.model]
|
this.model = [this.model]
|
||||||
}
|
}
|
||||||
|
@@ -307,7 +307,7 @@ ngb-tabset.vertical(type='pills', [activeId]='activeTab')
|
|||||||
td {{hotkey.id}}
|
td {{hotkey.id}}
|
||||||
td.pr-5
|
td.pr-5
|
||||||
multi-hotkey-input(
|
multi-hotkey-input(
|
||||||
[model]='getHotkey(hotkey.id)',
|
[model]='getHotkey(hotkey.id) || []',
|
||||||
(modelChange)='setHotkey(hotkey.id, $event); config.save(); docking.dock()'
|
(modelChange)='setHotkey(hotkey.id, $event); config.save(); docking.dock()'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@@ -24,7 +24,7 @@ export enum SSHAlgorithmType {
|
|||||||
export interface SSHConnection {
|
export interface SSHConnection {
|
||||||
name: string
|
name: string
|
||||||
host: string
|
host: string
|
||||||
port: number
|
port?: number
|
||||||
user: string
|
user: string
|
||||||
auth?: null|'password'|'publicKey'|'agent'|'keyboardInteractive'
|
auth?: null|'password'|'publicKey'|'agent'|'keyboardInteractive'
|
||||||
password?: string
|
password?: string
|
||||||
@@ -76,10 +76,10 @@ export class ForwardedPort {
|
|||||||
})
|
})
|
||||||
} else if (this.type === PortForwardType.Dynamic) {
|
} else if (this.type === PortForwardType.Dynamic) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
this.listener = socksv5.createServer((info, accept, reject) => {
|
this.listener = socksv5.createServer((info, acceptConnection, rejectConnection) => {
|
||||||
callback(
|
callback(
|
||||||
() => accept(true),
|
() => acceptConnection(true),
|
||||||
() => reject(),
|
() => rejectConnection(),
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
info.dstAddr,
|
info.dstAddr,
|
||||||
@@ -112,7 +112,7 @@ export class ForwardedPort {
|
|||||||
|
|
||||||
export class SSHSession extends BaseSession {
|
export class SSHSession extends BaseSession {
|
||||||
scripts?: LoginScript[]
|
scripts?: LoginScript[]
|
||||||
shell: ClientChannel
|
shell?: ClientChannel
|
||||||
ssh: Client
|
ssh: Client
|
||||||
forwardedPorts: ForwardedPort[] = []
|
forwardedPorts: ForwardedPort[] = []
|
||||||
logger: Logger
|
logger: Logger
|
||||||
@@ -123,7 +123,7 @@ export class SSHSession extends BaseSession {
|
|||||||
|
|
||||||
constructor (public connection: SSHConnection) {
|
constructor (public connection: SSHConnection) {
|
||||||
super()
|
super()
|
||||||
this.scripts = connection.scripts || []
|
this.scripts = connection.scripts ?? []
|
||||||
this.destroyed$.subscribe(() => {
|
this.destroyed$.subscribe(() => {
|
||||||
for (const port of this.forwardedPorts) {
|
for (const port of this.forwardedPorts) {
|
||||||
if (port.type === PortForwardType.Local) {
|
if (port.type === PortForwardType.Local) {
|
||||||
@@ -177,7 +177,7 @@ export class SSHSession extends BaseSession {
|
|||||||
|
|
||||||
if (match) {
|
if (match) {
|
||||||
this.logger.info('Executing script: "' + cmd + '"')
|
this.logger.info('Executing script: "' + cmd + '"')
|
||||||
this.shell.write(cmd + '\n')
|
this.shell!.write(cmd + '\n')
|
||||||
this.scripts = this.scripts.filter(x => x !== script)
|
this.scripts = this.scripts.filter(x => x !== script)
|
||||||
} else {
|
} else {
|
||||||
if (script.optional) {
|
if (script.optional) {
|
||||||
@@ -213,6 +213,7 @@ export class SSHSession extends BaseSession {
|
|||||||
const socket = new Socket()
|
const socket = new Socket()
|
||||||
socket.connect(forward.targetPort, forward.targetAddress)
|
socket.connect(forward.targetPort, forward.targetAddress)
|
||||||
socket.on('error', e => {
|
socket.on('error', e => {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-base-to-string
|
||||||
this.emitServiceMessage(colors.bgRed.black(' X ') + ` Could not forward the remote connection to ${forward.targetAddress}:${forward.targetPort}: ${e}`)
|
this.emitServiceMessage(colors.bgRed.black(' X ') + ` Could not forward the remote connection to ${forward.targetAddress}:${forward.targetPort}: ${e}`)
|
||||||
reject()
|
reject()
|
||||||
})
|
})
|
||||||
@@ -232,7 +233,7 @@ export class SSHSession extends BaseSession {
|
|||||||
|
|
||||||
this.ssh.on('x11', (details, accept, reject) => {
|
this.ssh.on('x11', (details, accept, reject) => {
|
||||||
this.logger.info(`Incoming X11 connection from ${details.srcIP}:${details.srcPort}`)
|
this.logger.info(`Incoming X11 connection from ${details.srcIP}:${details.srcPort}`)
|
||||||
const displaySpec = process.env.DISPLAY || ':0'
|
const displaySpec = process.env.DISPLAY ?? ':0'
|
||||||
this.logger.debug(`Trying display ${displaySpec}`)
|
this.logger.debug(`Trying display ${displaySpec}`)
|
||||||
const xHost = displaySpec.split(':')[0]
|
const xHost = displaySpec.split(':')[0]
|
||||||
const xDisplay = parseInt(displaySpec.split(':')[1].split('.')[0] || '0')
|
const xDisplay = parseInt(displaySpec.split(':')[1].split('.')[0] || '0')
|
||||||
@@ -243,6 +244,7 @@ export class SSHSession extends BaseSession {
|
|||||||
socket.connect(xPort, xHost)
|
socket.connect(xPort, xHost)
|
||||||
}
|
}
|
||||||
socket.on('error', e => {
|
socket.on('error', e => {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-base-to-string
|
||||||
this.emitServiceMessage(colors.bgRed.black(' X ') + ` Could not connect to the X server ${xHost}:${xPort}: ${e}`)
|
this.emitServiceMessage(colors.bgRed.black(' X ') + ` Could not connect to the X server ${xHost}:${xPort}: ${e}`)
|
||||||
reject()
|
reject()
|
||||||
})
|
})
|
||||||
@@ -273,27 +275,25 @@ export class SSHSession extends BaseSession {
|
|||||||
await fw.startLocalListener((accept, reject, sourceAddress, sourcePort, targetAddress, targetPort) => {
|
await fw.startLocalListener((accept, reject, sourceAddress, sourcePort, targetAddress, targetPort) => {
|
||||||
this.logger.info(`New connection on ${fw}`)
|
this.logger.info(`New connection on ${fw}`)
|
||||||
this.ssh.forwardOut(
|
this.ssh.forwardOut(
|
||||||
sourceAddress || '127.0.0.1',
|
sourceAddress ?? '127.0.0.1',
|
||||||
sourcePort || 0,
|
sourcePort ?? 0,
|
||||||
targetAddress,
|
targetAddress,
|
||||||
targetPort,
|
targetPort,
|
||||||
(err, stream) => {
|
(err, stream) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-base-to-string
|
||||||
this.emitServiceMessage(colors.bgRed.black(' X ') + ` Remote has rejected the forwarded connection to ${targetAddress}:${targetPort} via ${fw}: ${err}`)
|
this.emitServiceMessage(colors.bgRed.black(' X ') + ` Remote has rejected the forwarded connection to ${targetAddress}:${targetPort} via ${fw}: ${err}`)
|
||||||
reject()
|
return reject()
|
||||||
return
|
|
||||||
}
|
|
||||||
if (stream) {
|
|
||||||
const socket = accept()
|
|
||||||
stream.pipe(socket)
|
|
||||||
socket.pipe(stream)
|
|
||||||
stream.on('close', () => {
|
|
||||||
socket.destroy()
|
|
||||||
})
|
|
||||||
socket.on('close', () => {
|
|
||||||
stream.close()
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
const socket = accept()
|
||||||
|
stream.pipe(socket)
|
||||||
|
socket.pipe(stream)
|
||||||
|
stream.on('close', () => {
|
||||||
|
socket.destroy()
|
||||||
|
})
|
||||||
|
socket.on('close', () => {
|
||||||
|
stream.close()
|
||||||
|
})
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
@@ -308,6 +308,7 @@ export class SSHSession extends BaseSession {
|
|||||||
await new Promise((resolve, reject) => {
|
await new Promise((resolve, reject) => {
|
||||||
this.ssh.forwardIn(fw.host, fw.port, err => {
|
this.ssh.forwardIn(fw.host, fw.port, err => {
|
||||||
if (err) {
|
if (err) {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-base-to-string
|
||||||
this.emitServiceMessage(colors.bgRed.black(' X ') + ` Remote rejected port forwarding for ${fw}: ${err}`)
|
this.emitServiceMessage(colors.bgRed.black(' X ') + ` Remote rejected port forwarding for ${fw}: ${err}`)
|
||||||
return reject(err)
|
return reject(err)
|
||||||
}
|
}
|
||||||
@@ -345,7 +346,7 @@ export class SSHSession extends BaseSession {
|
|||||||
|
|
||||||
kill (signal?: string): void {
|
kill (signal?: string): void {
|
||||||
if (this.shell) {
|
if (this.shell) {
|
||||||
this.shell.signal(signal || 'TERM')
|
this.shell.signal(signal ?? 'TERM')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -362,6 +363,10 @@ export class SSHSession extends BaseSession {
|
|||||||
this.kill('TERM')
|
this.kill('TERM')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
supportsWorkingDirectory (): boolean {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
async getWorkingDirectory (): Promise<string|null> {
|
async getWorkingDirectory (): Promise<string|null> {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
@@ -383,7 +388,7 @@ export class SSHSession extends BaseSession {
|
|||||||
for (const script of this.scripts) {
|
for (const script of this.scripts) {
|
||||||
if (!script.expect) {
|
if (!script.expect) {
|
||||||
console.log('Executing script:', script.send)
|
console.log('Executing script:', script.send)
|
||||||
this.shell.write(script.send + '\n')
|
this.shell!.write(script.send + '\n')
|
||||||
this.scripts = this.scripts.filter(x => x !== script)
|
this.scripts = this.scripts.filter(x => x !== script)
|
||||||
} else {
|
} else {
|
||||||
break
|
break
|
||||||
@@ -397,3 +402,9 @@ export interface SSHConnectionGroup {
|
|||||||
name: string
|
name: string
|
||||||
connections: SSHConnection[]
|
connections: SSHConnection[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const ALGORITHM_BLACKLIST = [
|
||||||
|
// cause native crashes in node crypto, use EC instead
|
||||||
|
'diffie-hellman-group-exchange-sha256',
|
||||||
|
'diffie-hellman-group-exchange-sha1',
|
||||||
|
]
|
||||||
|
@@ -28,7 +28,7 @@ export class ButtonProvider extends ToolbarButtonProvider {
|
|||||||
weight: 5,
|
weight: 5,
|
||||||
title: 'SSH connections',
|
title: 'SSH connections',
|
||||||
touchBarNSImage: 'NSTouchBarOpenInBrowserTemplate',
|
touchBarNSImage: 'NSTouchBarOpenInBrowserTemplate',
|
||||||
click: async () => {
|
click: () => {
|
||||||
this.activate()
|
this.activate()
|
||||||
},
|
},
|
||||||
}]
|
}]
|
||||||
|
@@ -103,7 +103,7 @@
|
|||||||
.header
|
.header
|
||||||
.title Jump host
|
.title Jump host
|
||||||
select.form-control([(ngModel)]='connection.jumpHost')
|
select.form-control([(ngModel)]='connection.jumpHost')
|
||||||
option([ngValue]='null') None
|
option(value='') None
|
||||||
option([ngValue]='x.name', *ngFor='let x of config.store.ssh.connections') {{x.name}}
|
option([ngValue]='x.name', *ngFor='let x of config.store.ssh.connections') {{x.name}}
|
||||||
|
|
||||||
.form-line
|
.form-line
|
||||||
|
@@ -3,7 +3,7 @@ import { Component } from '@angular/core'
|
|||||||
import { NgbModal, NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'
|
import { NgbModal, NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'
|
||||||
import { ElectronService, HostAppService, ConfigService } from 'terminus-core'
|
import { ElectronService, HostAppService, ConfigService } from 'terminus-core'
|
||||||
import { PasswordStorageService } from '../services/passwordStorage.service'
|
import { PasswordStorageService } from '../services/passwordStorage.service'
|
||||||
import { SSHConnection, LoginScript, SSHAlgorithmType } from '../api'
|
import { SSHConnection, LoginScript, SSHAlgorithmType, ALGORITHM_BLACKLIST } from '../api'
|
||||||
import { PromptModalComponent } from './promptModal.component'
|
import { PromptModalComponent } from './promptModal.component'
|
||||||
import { ALGORITHMS } from 'ssh2-streams/lib/constants'
|
import { ALGORITHMS } from 'ssh2-streams/lib/constants'
|
||||||
|
|
||||||
@@ -40,18 +40,19 @@ export class EditConnectionModalComponent {
|
|||||||
[SSHAlgorithmType.CIPHER]: 'CIPHER',
|
[SSHAlgorithmType.CIPHER]: 'CIPHER',
|
||||||
[SSHAlgorithmType.HMAC]: 'HMAC',
|
[SSHAlgorithmType.HMAC]: 'HMAC',
|
||||||
}[k]
|
}[k]
|
||||||
this.supportedAlgorithms[k] = ALGORITHMS[supportedAlg]
|
this.supportedAlgorithms[k] = ALGORITHMS[supportedAlg].filter(x => !ALGORITHM_BLACKLIST.includes(x))
|
||||||
this.defaultAlgorithms[k] = ALGORITHMS[defaultAlg]
|
this.defaultAlgorithms[k] = ALGORITHMS[defaultAlg].filter(x => !ALGORITHM_BLACKLIST.includes(x))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async ngOnInit () {
|
async ngOnInit () {
|
||||||
this.hasSavedPassword = !!await this.passwordStorage.loadPassword(this.connection)
|
this.hasSavedPassword = !!await this.passwordStorage.loadPassword(this.connection)
|
||||||
this.connection.algorithms = this.connection.algorithms || {}
|
this.connection.algorithms = this.connection.algorithms ?? {}
|
||||||
this.connection.scripts = this.connection.scripts || []
|
this.connection.scripts = this.connection.scripts ?? []
|
||||||
this.connection.auth = this.connection.auth || null
|
this.connection.auth = this.connection.auth ?? null
|
||||||
|
|
||||||
for (const k of Object.values(SSHAlgorithmType)) {
|
for (const k of Object.values(SSHAlgorithmType)) {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
||||||
if (!this.connection.algorithms[k]) {
|
if (!this.connection.algorithms[k]) {
|
||||||
this.connection.algorithms[k] = this.defaultAlgorithms[k]
|
this.connection.algorithms[k] = this.defaultAlgorithms[k]
|
||||||
}
|
}
|
||||||
@@ -98,8 +99,8 @@ export class EditConnectionModalComponent {
|
|||||||
save () {
|
save () {
|
||||||
for (const k of Object.values(SSHAlgorithmType)) {
|
for (const k of Object.values(SSHAlgorithmType)) {
|
||||||
this.connection.algorithms![k] = Object.entries(this.algorithms[k])
|
this.connection.algorithms![k] = Object.entries(this.algorithms[k])
|
||||||
.filter(([_k, v]) => !!v)
|
.filter(([_, v]) => !!v)
|
||||||
.map(([k, _v]) => k)
|
.map(([key, _]) => key)
|
||||||
}
|
}
|
||||||
this.modalInstance.close(this.connection)
|
this.modalInstance.close(this.connection)
|
||||||
}
|
}
|
||||||
|
@@ -127,14 +127,14 @@ export class SSHSettingsTabComponent {
|
|||||||
this.childGroups = []
|
this.childGroups = []
|
||||||
|
|
||||||
for (const connection of this.connections) {
|
for (const connection of this.connections) {
|
||||||
connection.group = connection.group || null
|
connection.group = connection.group ?? null
|
||||||
let group = this.childGroups.find(x => x.name === connection.group)
|
let group = this.childGroups.find(x => x.name === connection.group)
|
||||||
if (!group) {
|
if (!group) {
|
||||||
group = {
|
group = {
|
||||||
name: connection.group!,
|
name: connection.group!,
|
||||||
connections: [],
|
connections: [],
|
||||||
}
|
}
|
||||||
this.childGroups.push(group!)
|
this.childGroups.push(group)
|
||||||
}
|
}
|
||||||
group.connections.push(connection)
|
group.connections.push(connection)
|
||||||
}
|
}
|
||||||
|
@@ -19,10 +19,13 @@ import { Subscription } from 'rxjs'
|
|||||||
animations: BaseTerminalTabComponent.animations,
|
animations: BaseTerminalTabComponent.animations,
|
||||||
})
|
})
|
||||||
export class SSHTabComponent extends BaseTerminalTabComponent {
|
export class SSHTabComponent extends BaseTerminalTabComponent {
|
||||||
connection: SSHConnection
|
connection?: SSHConnection
|
||||||
session: SSHSession
|
session?: SSHSession
|
||||||
private sessionStack: SSHSession[] = []
|
private sessionStack: SSHSession[] = []
|
||||||
private homeEndSubscription: Subscription
|
private homeEndSubscription: Subscription
|
||||||
|
private recentInputs = ''
|
||||||
|
private reconnectOffered = false
|
||||||
|
private sessionHandlers: Subscription[] = []
|
||||||
|
|
||||||
constructor (
|
constructor (
|
||||||
injector: Injector,
|
injector: Injector,
|
||||||
@@ -33,6 +36,10 @@ export class SSHTabComponent extends BaseTerminalTabComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit (): void {
|
ngOnInit (): void {
|
||||||
|
if (!this.connection) {
|
||||||
|
throw new Error('Connection not set')
|
||||||
|
}
|
||||||
|
|
||||||
this.logger = this.log.create('terminalTab')
|
this.logger = this.log.create('terminalTab')
|
||||||
|
|
||||||
this.enableDynamicTitle = !this.connection.disableDynamicTitle
|
this.enableDynamicTitle = !this.connection.disableDynamicTitle
|
||||||
@@ -53,26 +60,37 @@ export class SSHTabComponent extends BaseTerminalTabComponent {
|
|||||||
|
|
||||||
this.frontendReady$.pipe(first()).subscribe(() => {
|
this.frontendReady$.pipe(first()).subscribe(() => {
|
||||||
this.initializeSession()
|
this.initializeSession()
|
||||||
|
this.input$.subscribe(data => {
|
||||||
|
this.recentInputs += data
|
||||||
|
this.recentInputs = this.recentInputs.substring(this.recentInputs.length - 32)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
super.ngOnInit()
|
super.ngOnInit()
|
||||||
|
|
||||||
setImmediate(() => {
|
setImmediate(() => {
|
||||||
this.setTitle(this.connection.name)
|
this.setTitle(this.connection!.name)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async setupOneSession (session: SSHSession): Promise<void> {
|
async setupOneSession (session: SSHSession): Promise<void> {
|
||||||
if (session.connection.jumpHost) {
|
if (session.connection.jumpHost) {
|
||||||
const jumpConnection = this.config.store.ssh.connections.find(x => x.name === session.connection.jumpHost)
|
const jumpConnection: SSHConnection|null = this.config.store.ssh.connections.find(x => x.name === session.connection.jumpHost)
|
||||||
|
|
||||||
|
if (!jumpConnection) {
|
||||||
|
throw new Error(`${session.connection.host}: jump host "${session.connection.jumpHost}" not found in your config`)
|
||||||
|
}
|
||||||
|
|
||||||
const jumpSession = this.ssh.createSession(jumpConnection)
|
const jumpSession = this.ssh.createSession(jumpConnection)
|
||||||
|
|
||||||
await this.setupOneSession(jumpSession)
|
await this.setupOneSession(jumpSession)
|
||||||
|
|
||||||
jumpSession.destroyed$.subscribe(() => session.destroy())
|
this.sessionHandlers.push(
|
||||||
|
jumpSession.destroyed$.subscribe(() => session.destroy())
|
||||||
|
)
|
||||||
|
|
||||||
session.jumpStream = await new Promise((resolve, reject) => jumpSession.ssh.forwardOut(
|
session.jumpStream = await new Promise((resolve, reject) => jumpSession.ssh.forwardOut(
|
||||||
'127.0.0.1', 0, session.connection.host, session.connection.port,
|
'127.0.0.1', 0, session.connection.host, session.connection.port ?? 22,
|
||||||
(err, stream) => {
|
(err, stream) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
jumpSession.emitServiceMessage(colors.bgRed.black(' X ') + ` Could not set up port forward on ${jumpConnection.name}`)
|
jumpSession.emitServiceMessage(colors.bgRed.black(' X ') + ` Could not set up port forward on ${jumpConnection.name}`)
|
||||||
@@ -89,15 +107,31 @@ export class SSHTabComponent extends BaseTerminalTabComponent {
|
|||||||
this.sessionStack.push(session)
|
this.sessionStack.push(session)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.sessionHandlers.push(session.serviceMessage$.subscribe(msg => {
|
||||||
session.serviceMessage$.subscribe(msg => {
|
|
||||||
this.write(`\r\n${colors.black.bgWhite(' SSH ')} ${msg}\r\n`)
|
this.write(`\r\n${colors.black.bgWhite(' SSH ')} ${msg}\r\n`)
|
||||||
session.resize(this.size.columns, this.size.rows)
|
session.resize(this.size.columns, this.size.rows)
|
||||||
})
|
}))
|
||||||
|
|
||||||
session.destroyed$.subscribe(() => {
|
this.sessionHandlers.push(session.destroyed$.subscribe(() => {
|
||||||
this.write('\r\n' + colors.black.bgCyan(' SSH ') + ` ${session.connection.host}: session closed\r\n`)
|
if (
|
||||||
})
|
// Ctrl-D
|
||||||
|
this.recentInputs.charCodeAt(this.recentInputs.length - 1) === 4 ||
|
||||||
|
this.recentInputs.endsWith('exit\r')
|
||||||
|
) {
|
||||||
|
// User closed the session
|
||||||
|
this.destroy()
|
||||||
|
} else {
|
||||||
|
// Session was closed abruptly
|
||||||
|
this.write('\r\n' + colors.black.bgCyan(' SSH ') + ` ${session.connection.host}: session closed\r\n`)
|
||||||
|
if (!this.reconnectOffered) {
|
||||||
|
this.reconnectOffered = true
|
||||||
|
this.write('Press any key to reconnect\r\n')
|
||||||
|
this.input$.pipe(first()).subscribe(() => {
|
||||||
|
this.reconnect()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
|
||||||
this.write('\r\n' + colors.black.bgCyan(' SSH ') + ` Connecting to ${session.connection.host}\r\n`)
|
this.write('\r\n' + colors.black.bgCyan(' SSH ') + ` Connecting to ${session.connection.host}\r\n`)
|
||||||
|
|
||||||
@@ -125,6 +159,7 @@ export class SSHTabComponent extends BaseTerminalTabComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async initializeSession (): Promise<void> {
|
async initializeSession (): Promise<void> {
|
||||||
|
this.reconnectOffered = false
|
||||||
if (!this.connection) {
|
if (!this.connection) {
|
||||||
this.logger.error('No SSH connection info supplied')
|
this.logger.error('No SSH connection info supplied')
|
||||||
return
|
return
|
||||||
@@ -132,7 +167,11 @@ export class SSHTabComponent extends BaseTerminalTabComponent {
|
|||||||
|
|
||||||
this.session = this.ssh.createSession(this.connection)
|
this.session = this.ssh.createSession(this.connection)
|
||||||
|
|
||||||
await this.setupOneSession(this.session)
|
try {
|
||||||
|
await this.setupOneSession(this.session)
|
||||||
|
} catch (e) {
|
||||||
|
this.write(colors.black.bgRed(' X ') + ' ' + colors.red(e.message) + '\r\n')
|
||||||
|
}
|
||||||
|
|
||||||
this.attachSessionHandlers()
|
this.attachSessionHandlers()
|
||||||
|
|
||||||
@@ -150,27 +189,31 @@ export class SSHTabComponent extends BaseTerminalTabComponent {
|
|||||||
|
|
||||||
showPortForwarding (): void {
|
showPortForwarding (): void {
|
||||||
const modal = this.ngbModal.open(SSHPortForwardingModalComponent).componentInstance as SSHPortForwardingModalComponent
|
const modal = this.ngbModal.open(SSHPortForwardingModalComponent).componentInstance as SSHPortForwardingModalComponent
|
||||||
modal.session = this.session
|
modal.session = this.session!
|
||||||
}
|
}
|
||||||
|
|
||||||
async reconnect (): Promise<void> {
|
async reconnect (): Promise<void> {
|
||||||
|
for (const s of this.sessionHandlers) {
|
||||||
|
s.unsubscribe()
|
||||||
|
}
|
||||||
|
this.sessionHandlers = []
|
||||||
this.session?.destroy()
|
this.session?.destroy()
|
||||||
await this.initializeSession()
|
await this.initializeSession()
|
||||||
this.session.releaseInitialDataBuffer()
|
this.session?.releaseInitialDataBuffer()
|
||||||
}
|
}
|
||||||
|
|
||||||
async canClose (): Promise<boolean> {
|
async canClose (): Promise<boolean> {
|
||||||
if (!this.session?.open) {
|
if (!this.session?.open) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
if (!(this.connection.warnOnClose ?? this.config.store.ssh.warnOnClose)) {
|
if (!(this.connection?.warnOnClose ?? this.config.store.ssh.warnOnClose)) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return (await this.electron.showMessageBox(
|
return (await this.electron.showMessageBox(
|
||||||
this.hostApp.getWindow(),
|
this.hostApp.getWindow(),
|
||||||
{
|
{
|
||||||
type: 'warning',
|
type: 'warning',
|
||||||
message: `Disconnect from ${this.connection.host}?`,
|
message: `Disconnect from ${this.connection?.host}?`,
|
||||||
buttons: ['Cancel', 'Disconnect'],
|
buttons: ['Cancel', 'Disconnect'],
|
||||||
defaultId: 1,
|
defaultId: 1,
|
||||||
}
|
}
|
||||||
|
@@ -7,7 +7,7 @@ import { SSHTabComponent } from './components/sshTab.component'
|
|||||||
@Injectable()
|
@Injectable()
|
||||||
export class RecoveryProvider extends TabRecoveryProvider {
|
export class RecoveryProvider extends TabRecoveryProvider {
|
||||||
async recover (recoveryToken: RecoveryToken): Promise<RecoveredTab|null> {
|
async recover (recoveryToken: RecoveryToken): Promise<RecoveredTab|null> {
|
||||||
if (recoveryToken?.type === 'app:ssh-tab') {
|
if (recoveryToken.type === 'app:ssh-tab') {
|
||||||
return {
|
return {
|
||||||
type: SSHTabComponent,
|
type: SSHTabComponent,
|
||||||
options: {
|
options: {
|
||||||
|
@@ -12,7 +12,7 @@ import * as sshpk from 'sshpk'
|
|||||||
import { ToastrService } from 'ngx-toastr'
|
import { ToastrService } from 'ngx-toastr'
|
||||||
import { HostAppService, Platform, Logger, LogService, ElectronService, AppService, SelectorOption, ConfigService } from 'terminus-core'
|
import { HostAppService, Platform, Logger, LogService, ElectronService, AppService, SelectorOption, ConfigService } from 'terminus-core'
|
||||||
import { SettingsTabComponent } from 'terminus-settings'
|
import { SettingsTabComponent } from 'terminus-settings'
|
||||||
import { SSHConnection, SSHSession } from '../api'
|
import { ALGORITHM_BLACKLIST, SSHConnection, SSHSession } from '../api'
|
||||||
import { PromptModalComponent } from '../components/promptModal.component'
|
import { PromptModalComponent } from '../components/promptModal.component'
|
||||||
import { PasswordStorageService } from './passwordStorage.service'
|
import { PasswordStorageService } from './passwordStorage.service'
|
||||||
import { SSHTabComponent } from '../components/sshTab.component'
|
import { SSHTabComponent } from '../components/sshTab.component'
|
||||||
@@ -98,7 +98,7 @@ export class SSHService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const sshFormatKey = parsedKey!.toString('openssh')
|
const sshFormatKey = parsedKey.toString('openssh')
|
||||||
const temp = await openTemp()
|
const temp = await openTemp()
|
||||||
fs.close(temp.fd)
|
fs.close(temp.fd)
|
||||||
await fs.writeFile(temp.path, sshFormatKey)
|
await fs.writeFile(temp.path, sshFormatKey)
|
||||||
@@ -147,6 +147,10 @@ export class SSHService {
|
|||||||
session.ssh = ssh
|
session.ssh = ssh
|
||||||
let connected = false
|
let connected = false
|
||||||
let savedPassword: string|null = null
|
let savedPassword: string|null = null
|
||||||
|
const algorithms = {}
|
||||||
|
for (const key of Object.keys(session.connection.algorithms ?? {})) {
|
||||||
|
algorithms[key] = session.connection.algorithms![key].filter(x => !ALGORITHM_BLACKLIST.includes(x))
|
||||||
|
}
|
||||||
await new Promise(async (resolve, reject) => {
|
await new Promise(async (resolve, reject) => {
|
||||||
ssh.on('ready', () => {
|
ssh.on('ready', () => {
|
||||||
connected = true
|
connected = true
|
||||||
@@ -161,6 +165,7 @@ export class SSHService {
|
|||||||
}
|
}
|
||||||
this.zone.run(() => {
|
this.zone.run(() => {
|
||||||
if (connected) {
|
if (connected) {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-base-to-string
|
||||||
this.toastr.error(error.toString())
|
this.toastr.error(error.toString())
|
||||||
} else {
|
} else {
|
||||||
reject(error)
|
reject(error)
|
||||||
@@ -209,6 +214,7 @@ export class SSHService {
|
|||||||
if (await fs.exists(WINDOWS_OPENSSH_AGENT_PIPE)) {
|
if (await fs.exists(WINDOWS_OPENSSH_AGENT_PIPE)) {
|
||||||
agent = WINDOWS_OPENSSH_AGENT_PIPE
|
agent = WINDOWS_OPENSSH_AGENT_PIPE
|
||||||
} else {
|
} else {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-shadow
|
||||||
const pageantRunning = await new Promise<boolean>(resolve => {
|
const pageantRunning = await new Promise<boolean>(resolve => {
|
||||||
windowsProcessTreeNative.getProcessList(list => { // eslint-disable-line block-scoped-var
|
windowsProcessTreeNative.getProcessList(list => { // eslint-disable-line block-scoped-var
|
||||||
resolve(list.some(x => x.name === 'pageant.exe'))
|
resolve(list.some(x => x.name === 'pageant.exe'))
|
||||||
@@ -249,14 +255,14 @@ export class SSHService {
|
|||||||
try {
|
try {
|
||||||
ssh.connect({
|
ssh.connect({
|
||||||
host: session.connection.host,
|
host: session.connection.host,
|
||||||
port: session.connection.port || 22,
|
port: session.connection.port ?? 22,
|
||||||
username: session.connection.user,
|
username: session.connection.user,
|
||||||
password: session.connection.privateKey ? undefined : '',
|
password: session.connection.privateKey ? undefined : '',
|
||||||
privateKey: privateKey || undefined,
|
privateKey: privateKey ?? undefined,
|
||||||
tryKeyboard: true,
|
tryKeyboard: true,
|
||||||
agent: agent || undefined,
|
agent: agent ?? undefined,
|
||||||
agentForward: session.connection.agentForward && !!agent,
|
agentForward: session.connection.agentForward && !!agent,
|
||||||
keepaliveInterval: session.connection.keepaliveInterval,
|
keepaliveInterval: session.connection.keepaliveInterval ?? 15000,
|
||||||
keepaliveCountMax: session.connection.keepaliveCountMax,
|
keepaliveCountMax: session.connection.keepaliveCountMax,
|
||||||
readyTimeout: session.connection.readyTimeout,
|
readyTimeout: session.connection.readyTimeout,
|
||||||
hostVerifier: (digest: string) => {
|
hostVerifier: (digest: string) => {
|
||||||
@@ -265,7 +271,7 @@ export class SSHService {
|
|||||||
return true
|
return true
|
||||||
},
|
},
|
||||||
hostHash: 'sha256' as any,
|
hostHash: 'sha256' as any,
|
||||||
algorithms: session.connection.algorithms,
|
algorithms,
|
||||||
sock: session.jumpStream,
|
sock: session.jumpStream,
|
||||||
authHandler: methodsLeft => {
|
authHandler: methodsLeft => {
|
||||||
while (true) {
|
while (true) {
|
||||||
@@ -284,7 +290,7 @@ export class SSHService {
|
|||||||
} as any)
|
} as any)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.toastr.error(e.message)
|
this.toastr.error(e.message)
|
||||||
reject(e)
|
return reject(e)
|
||||||
}
|
}
|
||||||
|
|
||||||
let keychainPasswordUsed = false
|
let keychainPasswordUsed = false
|
||||||
@@ -358,7 +364,7 @@ export class SSHService {
|
|||||||
name: connection.group!,
|
name: connection.group!,
|
||||||
connections: [],
|
connections: [],
|
||||||
}
|
}
|
||||||
groups.push(group!)
|
groups.push(group)
|
||||||
}
|
}
|
||||||
group.connections.push(connection)
|
group.connections.push(connection)
|
||||||
}
|
}
|
||||||
@@ -398,12 +404,10 @@ export class SSHService {
|
|||||||
{ connection }
|
{ connection }
|
||||||
) as SSHTabComponent
|
) as SSHTabComponent
|
||||||
if (connection.color) {
|
if (connection.color) {
|
||||||
(this.app.getParentTab(tab) || tab).color = connection.color
|
(this.app.getParentTab(tab) ?? tab).color = connection.color
|
||||||
}
|
}
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => this.app.activeTab?.emitFocused())
|
||||||
this.app.activeTab?.emitFocused()
|
|
||||||
})
|
|
||||||
|
|
||||||
return tab
|
return tab
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
@@ -44,14 +44,14 @@ export class WinSCPContextMenu extends TabContextMenuItemProvider {
|
|||||||
if (!this.getPath()) {
|
if (!this.getPath()) {
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
if (!(tab instanceof SSHTabComponent)) {
|
if (!(tab instanceof SSHTabComponent) || !tab.connection) {
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
label: 'Launch WinSCP',
|
label: 'Launch WinSCP',
|
||||||
click: (): void => {
|
click: (): void => {
|
||||||
this.launchWinSCP(tab.connection)
|
this.launchWinSCP(tab.connection!)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
@@ -2,12 +2,7 @@
|
|||||||
# yarn lockfile v1
|
# yarn lockfile v1
|
||||||
|
|
||||||
|
|
||||||
"@types/node@*":
|
"@types/node@*", "@types/node@14.14.14":
|
||||||
version "14.14.7"
|
|
||||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.7.tgz#8ea1e8f8eae2430cf440564b98c6dfce1ec5945d"
|
|
||||||
integrity sha512-Zw1vhUSQZYw+7u5dAwNbIA9TuTotpzY/OF7sJM9FqPOF3SPjKnxrjoTktXDZgUjybf4cWVBP7O8wvKdSaGHweg==
|
|
||||||
|
|
||||||
"@types/node@14.14.14":
|
|
||||||
version "14.14.14"
|
version "14.14.14"
|
||||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.14.tgz#f7fd5f3cc8521301119f63910f0fb965c7d761ae"
|
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.14.tgz#f7fd5f3cc8521301119f63910f0fb965c7d761ae"
|
||||||
integrity sha512-UHnOPWVWV1z+VV8k6L1HhG7UbGBgIdghqF3l9Ny9ApPghbjICXkUJSd/b9gOgQfjM1r+37cipdw/HJ3F6ICEnQ==
|
integrity sha512-UHnOPWVWV1z+VV8k6L1HhG7UbGBgIdghqF3l9Ny9ApPghbjICXkUJSd/b9gOgQfjM1r+37cipdw/HJ3F6ICEnQ==
|
||||||
@@ -20,9 +15,9 @@
|
|||||||
"@types/node" "*"
|
"@types/node" "*"
|
||||||
|
|
||||||
"@types/ssh2@^0.5.35":
|
"@types/ssh2@^0.5.35":
|
||||||
version "0.5.45"
|
version "0.5.46"
|
||||||
resolved "https://registry.yarnpkg.com/@types/ssh2/-/ssh2-0.5.45.tgz#14e293ec2a4d4c8a5434a7989a676b87340aa870"
|
resolved "https://registry.yarnpkg.com/@types/ssh2/-/ssh2-0.5.46.tgz#e12341a242aea0e98ac2dec89e039bf421fd3584"
|
||||||
integrity sha512-SAQITTyO/jOoskSAw2T/9sveX4lhTzx7zdeYR0t04RMhZQrEIzvrAoCStSxYwvwZ5ofek1JWeW9x2yOK3GOUlg==
|
integrity sha512-1pC8FHrMPYdkLoUOwTYYifnSEPzAFZRsp3JFC/vokQ+dRrVI+hDBwz0SNmQ3pL6h39OSZlPs0uCG7wKJkftnaA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@types/node" "*"
|
"@types/node" "*"
|
||||||
"@types/ssh2-streams" "*"
|
"@types/ssh2-streams" "*"
|
||||||
|
@@ -18,6 +18,7 @@ import { TerminalDecorator } from './decorator'
|
|||||||
/** @hidden */
|
/** @hidden */
|
||||||
export interface ToastrServiceProxy {
|
export interface ToastrServiceProxy {
|
||||||
info: (_: string) => void
|
info: (_: string) => void
|
||||||
|
error: (_: string) => void
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* A class to base your custom terminal tabs on
|
* A class to base your custom terminal tabs on
|
||||||
@@ -35,8 +36,8 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
|
|||||||
]),
|
]),
|
||||||
])]
|
])]
|
||||||
|
|
||||||
session: BaseSession
|
session?: BaseSession
|
||||||
savedState: any
|
savedState?: any
|
||||||
|
|
||||||
@Input() zoom = 0
|
@Input() zoom = 0
|
||||||
|
|
||||||
@@ -51,7 +52,7 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
|
|||||||
/** @hidden */
|
/** @hidden */
|
||||||
@HostBinding('class.top-padded') topPadded: boolean
|
@HostBinding('class.top-padded') topPadded: boolean
|
||||||
|
|
||||||
frontend: Frontend
|
frontend?: Frontend
|
||||||
|
|
||||||
/** @hidden */
|
/** @hidden */
|
||||||
frontendIsReady = false
|
frontendIsReady = false
|
||||||
@@ -83,7 +84,7 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
|
|||||||
protected terminalContainersService: TerminalFrontendService
|
protected terminalContainersService: TerminalFrontendService
|
||||||
protected toastr: ToastrServiceProxy
|
protected toastr: ToastrServiceProxy
|
||||||
protected log: LogService
|
protected log: LogService
|
||||||
protected decorators: TerminalDecorator[]
|
protected decorators: TerminalDecorator[] = []
|
||||||
protected contextMenuProviders: TabContextMenuItemProvider[]
|
protected contextMenuProviders: TabContextMenuItemProvider[]
|
||||||
// Deps end
|
// Deps end
|
||||||
|
|
||||||
@@ -95,10 +96,29 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
|
|||||||
private termContainerSubscriptions: Subscription[] = []
|
private termContainerSubscriptions: Subscription[] = []
|
||||||
private allFocusModeSubscription: Subscription|null = null
|
private allFocusModeSubscription: Subscription|null = null
|
||||||
|
|
||||||
get input$ (): Observable<Buffer> { return this.frontend.input$ }
|
get input$ (): Observable<Buffer> {
|
||||||
|
if (!this.frontend) {
|
||||||
|
throw new Error('Frontend not ready')
|
||||||
|
}
|
||||||
|
return this.frontend.input$
|
||||||
|
}
|
||||||
|
|
||||||
get output$ (): Observable<string> { return this.output }
|
get output$ (): Observable<string> { return this.output }
|
||||||
get resize$ (): Observable<ResizeEvent> { return this.frontend.resize$ }
|
|
||||||
get alternateScreenActive$ (): Observable<boolean> { return this.frontend.alternateScreenActive$ }
|
get resize$ (): Observable<ResizeEvent> {
|
||||||
|
if (!this.frontend) {
|
||||||
|
throw new Error('Frontend not ready')
|
||||||
|
}
|
||||||
|
return this.frontend.resize$
|
||||||
|
}
|
||||||
|
|
||||||
|
get alternateScreenActive$ (): Observable<boolean> {
|
||||||
|
if (!this.frontend) {
|
||||||
|
throw new Error('Frontend not ready')
|
||||||
|
}
|
||||||
|
return this.frontend.alternateScreenActive$
|
||||||
|
}
|
||||||
|
|
||||||
get frontendReady$ (): Observable<void> { return this.frontendReady }
|
get frontendReady$ (): Observable<void> { return this.frontendReady }
|
||||||
|
|
||||||
constructor (protected injector: Injector) {
|
constructor (protected injector: Injector) {
|
||||||
@@ -119,16 +139,15 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
|
|||||||
this.contextMenuProviders = injector.get<any>(TabContextMenuItemProvider, null, InjectFlags.Optional) as TabContextMenuItemProvider[]
|
this.contextMenuProviders = injector.get<any>(TabContextMenuItemProvider, null, InjectFlags.Optional) as TabContextMenuItemProvider[]
|
||||||
|
|
||||||
this.logger = this.log.create('baseTerminalTab')
|
this.logger = this.log.create('baseTerminalTab')
|
||||||
this.decorators = this.decorators || []
|
|
||||||
this.setTitle('Terminal')
|
this.setTitle('Terminal')
|
||||||
|
|
||||||
this.hotkeysSubscription = this.hotkeys.matchedHotkey.subscribe(hotkey => {
|
this.hotkeysSubscription = this.hotkeys.matchedHotkey.subscribe(async hotkey => {
|
||||||
if (!this.hasFocus) {
|
if (!this.hasFocus) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
switch (hotkey) {
|
switch (hotkey) {
|
||||||
case 'ctrl-c':
|
case 'ctrl-c':
|
||||||
if (this.frontend.getSelection()) {
|
if (this.frontend?.getSelection()) {
|
||||||
this.frontend.copySelection()
|
this.frontend.copySelection()
|
||||||
this.frontend.clearSelection()
|
this.frontend.clearSelection()
|
||||||
this.toastr.info('Copied')
|
this.toastr.info('Copied')
|
||||||
@@ -137,15 +156,15 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
|
|||||||
}
|
}
|
||||||
break
|
break
|
||||||
case 'copy':
|
case 'copy':
|
||||||
this.frontend.copySelection()
|
this.frontend?.copySelection()
|
||||||
this.frontend.clearSelection()
|
this.frontend?.clearSelection()
|
||||||
this.toastr.info('Copied')
|
this.toastr.info('Copied')
|
||||||
break
|
break
|
||||||
case 'paste':
|
case 'paste':
|
||||||
this.paste()
|
this.paste()
|
||||||
break
|
break
|
||||||
case 'clear':
|
case 'clear':
|
||||||
this.frontend.clear()
|
this.frontend?.clear()
|
||||||
break
|
break
|
||||||
case 'zoom-in':
|
case 'zoom-in':
|
||||||
this.zoomIn()
|
this.zoomIn()
|
||||||
@@ -189,6 +208,9 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
|
|||||||
case 'pane-focus-all':
|
case 'pane-focus-all':
|
||||||
this.focusAllPanes()
|
this.focusAllPanes()
|
||||||
break
|
break
|
||||||
|
case 'copy-current-path':
|
||||||
|
this.copyCurrentPath()
|
||||||
|
break
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
this.bellPlayer = document.createElement('audio')
|
this.bellPlayer = document.createElement('audio')
|
||||||
@@ -201,7 +223,7 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
|
|||||||
ngOnInit (): void {
|
ngOnInit (): void {
|
||||||
this.focused$.subscribe(() => {
|
this.focused$.subscribe(() => {
|
||||||
this.configure()
|
this.configure()
|
||||||
this.frontend.focus()
|
this.frontend?.focus()
|
||||||
})
|
})
|
||||||
|
|
||||||
this.frontend = this.terminalContainersService.getFrontend(this.session)
|
this.frontend = this.terminalContainersService.getFrontend(this.session)
|
||||||
@@ -223,10 +245,10 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
|
|||||||
})
|
})
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.session.resize(columns, rows)
|
this.session?.resize(columns, rows)
|
||||||
}, 1000)
|
}, 1000)
|
||||||
|
|
||||||
this.session.releaseInitialDataBuffer()
|
this.session?.releaseInitialDataBuffer()
|
||||||
})
|
})
|
||||||
|
|
||||||
this.alternateScreenActive$.subscribe(x => {
|
this.alternateScreenActive$.subscribe(x => {
|
||||||
@@ -242,12 +264,12 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
|
|||||||
|
|
||||||
setImmediate(() => {
|
setImmediate(() => {
|
||||||
if (this.hasFocus) {
|
if (this.hasFocus) {
|
||||||
this.frontend.attach(this.content.nativeElement)
|
this.frontend!.attach(this.content.nativeElement)
|
||||||
this.frontend.configure()
|
this.frontend!.configure()
|
||||||
} else {
|
} else {
|
||||||
this.focused$.pipe(first()).subscribe(() => {
|
this.focused$.pipe(first()).subscribe(() => {
|
||||||
this.frontend.attach(this.content.nativeElement)
|
this.frontend!.attach(this.content.nativeElement)
|
||||||
this.frontend.configure()
|
this.frontend!.configure()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -264,7 +286,7 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
|
|||||||
|
|
||||||
this.frontend.bell$.subscribe(() => {
|
this.frontend.bell$.subscribe(() => {
|
||||||
if (this.config.store.terminal.bell === 'visual') {
|
if (this.config.store.terminal.bell === 'visual') {
|
||||||
this.frontend.visualBell()
|
this.frontend?.visualBell()
|
||||||
}
|
}
|
||||||
if (this.config.store.terminal.bell === 'audible') {
|
if (this.config.store.terminal.bell === 'audible') {
|
||||||
this.bellPlayer.play()
|
this.bellPlayer.play()
|
||||||
@@ -295,9 +317,9 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
|
|||||||
if (!(data instanceof Buffer)) {
|
if (!(data instanceof Buffer)) {
|
||||||
data = Buffer.from(data, 'utf-8')
|
data = Buffer.from(data, 'utf-8')
|
||||||
}
|
}
|
||||||
this.session.write(data)
|
this.session?.write(data)
|
||||||
if (this.config.store.terminal.scrollOnInput) {
|
if (this.config.store.terminal.scrollOnInput) {
|
||||||
this.frontend.scrollToBottom()
|
this.frontend?.scrollToBottom()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -305,6 +327,10 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
|
|||||||
* Feeds input into the terminal frontend
|
* Feeds input into the terminal frontend
|
||||||
*/
|
*/
|
||||||
write (data: string): void {
|
write (data: string): void {
|
||||||
|
if (!this.frontend) {
|
||||||
|
throw new Error('Frontend not ready')
|
||||||
|
}
|
||||||
|
|
||||||
const percentageMatch = /(^|[^\d])(\d+(\.\d+)?)%([^\d]|$)/.exec(data)
|
const percentageMatch = /(^|[^\d])(\d+(\.\d+)?)%([^\d]|$)/.exec(data)
|
||||||
if (!this.alternateScreenActive && percentageMatch) {
|
if (!this.alternateScreenActive && percentageMatch) {
|
||||||
const percentage = percentageMatch[3] ? parseFloat(percentageMatch[2]) : parseInt(percentageMatch[2])
|
const percentage = percentageMatch[3] ? parseFloat(percentageMatch[2]) : parseInt(percentageMatch[2])
|
||||||
@@ -357,7 +383,7 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
|
|||||||
* Applies the user settings to the terminal
|
* Applies the user settings to the terminal
|
||||||
*/
|
*/
|
||||||
configure (): void {
|
configure (): void {
|
||||||
this.frontend.configure()
|
this.frontend?.configure()
|
||||||
|
|
||||||
this.topPadded = this.hostApp.platform === Platform.macOS
|
this.topPadded = this.hostApp.platform === Platform.macOS
|
||||||
&& this.config.store.appearance.frame === 'thin'
|
&& this.config.store.appearance.frame === 'thin'
|
||||||
@@ -374,17 +400,17 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
|
|||||||
|
|
||||||
zoomIn (): void {
|
zoomIn (): void {
|
||||||
this.zoom++
|
this.zoom++
|
||||||
this.frontend.setZoom(this.zoom)
|
this.frontend?.setZoom(this.zoom)
|
||||||
}
|
}
|
||||||
|
|
||||||
zoomOut (): void {
|
zoomOut (): void {
|
||||||
this.zoom--
|
this.zoom--
|
||||||
this.frontend.setZoom(this.zoom)
|
this.frontend?.setZoom(this.zoom)
|
||||||
}
|
}
|
||||||
|
|
||||||
resetZoom (): void {
|
resetZoom (): void {
|
||||||
this.zoom = 0
|
this.zoom = 0
|
||||||
this.frontend.setZoom(this.zoom)
|
this.frontend?.setZoom(this.zoom)
|
||||||
}
|
}
|
||||||
|
|
||||||
focusAllPanes (): void {
|
focusAllPanes (): void {
|
||||||
@@ -394,13 +420,13 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
|
|||||||
if (this.parent instanceof SplitTabComponent) {
|
if (this.parent instanceof SplitTabComponent) {
|
||||||
this.parent._allFocusMode = true
|
this.parent._allFocusMode = true
|
||||||
this.parent.layout()
|
this.parent.layout()
|
||||||
this.allFocusModeSubscription = this.frontend.input$.subscribe(data => {
|
this.allFocusModeSubscription = this.frontend?.input$.subscribe(data => {
|
||||||
for (const tab of (this.parent as SplitTabComponent).getAllTabs()) {
|
for (const tab of (this.parent as SplitTabComponent).getAllTabs()) {
|
||||||
if (tab !== this && tab instanceof BaseTerminalTabComponent) {
|
if (tab !== this && tab instanceof BaseTerminalTabComponent) {
|
||||||
tab.sendInput(data)
|
tab.sendInput(data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
}) ?? null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -416,9 +442,22 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async copyCurrentPath (): Promise<void> {
|
||||||
|
let cwd: string|null = null
|
||||||
|
if (this.session?.supportsWorkingDirectory()) {
|
||||||
|
cwd = await this.session.getWorkingDirectory()
|
||||||
|
}
|
||||||
|
if (cwd) {
|
||||||
|
this.electron.clipboard.writeText(cwd)
|
||||||
|
this.toastr.info('Copied')
|
||||||
|
} else {
|
||||||
|
this.toastr.error('Shell does not support current path detection')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** @hidden */
|
/** @hidden */
|
||||||
ngOnDestroy (): void {
|
ngOnDestroy (): void {
|
||||||
this.frontend.detach(this.content.nativeElement)
|
this.frontend?.detach(this.content.nativeElement)
|
||||||
this.detachTermContainerHandlers()
|
this.detachTermContainerHandlers()
|
||||||
this.config.enabledServices(this.decorators).forEach(decorator => {
|
this.config.enabledServices(this.decorators).forEach(decorator => {
|
||||||
try {
|
try {
|
||||||
@@ -451,6 +490,10 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
|
|||||||
protected attachTermContainerHandlers (): void {
|
protected attachTermContainerHandlers (): void {
|
||||||
this.detachTermContainerHandlers()
|
this.detachTermContainerHandlers()
|
||||||
|
|
||||||
|
if (!this.frontend) {
|
||||||
|
throw new Error('Frontend not ready')
|
||||||
|
}
|
||||||
|
|
||||||
const maybeConfigure = () => {
|
const maybeConfigure = () => {
|
||||||
if (this.hasFocus) {
|
if (this.hasFocus) {
|
||||||
setTimeout(() => this.configure(), 250)
|
setTimeout(() => this.configure(), 250)
|
||||||
@@ -464,8 +507,8 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
|
|||||||
}
|
}
|
||||||
})),
|
})),
|
||||||
|
|
||||||
this.focused$.subscribe(() => this.frontend.enableResizing = true),
|
this.focused$.subscribe(() => this.frontend && (this.frontend.enableResizing = true)),
|
||||||
this.blurred$.subscribe(() => this.frontend.enableResizing = false),
|
this.blurred$.subscribe(() => this.frontend && (this.frontend.enableResizing = false)),
|
||||||
|
|
||||||
this.frontend.mouseEvent$.subscribe(async event => {
|
this.frontend.mouseEvent$.subscribe(async event => {
|
||||||
if (event.type === 'mousedown') {
|
if (event.type === 'mousedown') {
|
||||||
@@ -525,6 +568,10 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected attachSessionHandlers (destroyOnSessionClose = false): void {
|
protected attachSessionHandlers (destroyOnSessionClose = false): void {
|
||||||
|
if (!this.session) {
|
||||||
|
throw new Error('Session not set')
|
||||||
|
}
|
||||||
|
|
||||||
// this.session.output$.bufferTime(10).subscribe((datas) => {
|
// this.session.output$.bufferTime(10).subscribe((datas) => {
|
||||||
this.session.output$.subscribe(data => {
|
this.session.output$.subscribe(data => {
|
||||||
if (this.enablePassthrough) {
|
if (this.enablePassthrough) {
|
||||||
@@ -537,7 +584,7 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
|
|||||||
|
|
||||||
if (destroyOnSessionClose) {
|
if (destroyOnSessionClose) {
|
||||||
this.sessionCloseSubscription = this.session.closed$.subscribe(() => {
|
this.sessionCloseSubscription = this.session.closed$.subscribe(() => {
|
||||||
this.frontend.destroy()
|
this.frontend?.destroy()
|
||||||
this.destroy()
|
this.destroy()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@@ -17,7 +17,7 @@ export abstract class TerminalDecorator {
|
|||||||
* Make sure to call super()
|
* Make sure to call super()
|
||||||
*/
|
*/
|
||||||
detach (terminal: BaseTerminalTabComponent): void {
|
detach (terminal: BaseTerminalTabComponent): void {
|
||||||
for (const s of this.smartSubscriptions.get(terminal) || []) {
|
for (const s of this.smartSubscriptions.get(terminal) ?? []) {
|
||||||
s.unsubscribe()
|
s.unsubscribe()
|
||||||
}
|
}
|
||||||
this.smartSubscriptions.delete(terminal)
|
this.smartSubscriptions.delete(terminal)
|
||||||
@@ -26,7 +26,10 @@ export abstract class TerminalDecorator {
|
|||||||
/**
|
/**
|
||||||
* Automatically cancel @subscription once detached from @terminal
|
* Automatically cancel @subscription once detached from @terminal
|
||||||
*/
|
*/
|
||||||
protected subscribeUntilDetached (terminal: BaseTerminalTabComponent, subscription: Subscription): void {
|
protected subscribeUntilDetached (terminal: BaseTerminalTabComponent, subscription?: Subscription): void {
|
||||||
|
if (!subscription) {
|
||||||
|
return
|
||||||
|
}
|
||||||
if (!this.smartSubscriptions.has(terminal)) {
|
if (!this.smartSubscriptions.has(terminal)) {
|
||||||
this.smartSubscriptions.set(terminal, [])
|
this.smartSubscriptions.set(terminal, [])
|
||||||
}
|
}
|
||||||
|
@@ -6,7 +6,7 @@ export interface ResizeEvent {
|
|||||||
export interface SessionOptions {
|
export interface SessionOptions {
|
||||||
name?: string
|
name?: string
|
||||||
command: string
|
command: string
|
||||||
args: string[]
|
args?: string[]
|
||||||
cwd?: string
|
cwd?: string
|
||||||
env?: Record<string, string>
|
env?: Record<string, string>
|
||||||
width?: number
|
width?: number
|
||||||
|
@@ -93,11 +93,11 @@ export class ColorSchemeSettingsTabComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getCurrentSchemeName () {
|
getCurrentSchemeName () {
|
||||||
return (this.currentCustomScheme || this.currentStockScheme)?.name || 'Custom'
|
return (this.currentCustomScheme ?? this.currentStockScheme)?.name ?? 'Custom'
|
||||||
}
|
}
|
||||||
|
|
||||||
findMatchingScheme (scheme: TerminalColorScheme, schemes: TerminalColorScheme[]) {
|
findMatchingScheme (scheme: TerminalColorScheme, schemes: TerminalColorScheme[]) {
|
||||||
return schemes.find(x => deepEqual(x, scheme)) || null
|
return schemes.find(x => deepEqual(x, scheme)) ?? null
|
||||||
}
|
}
|
||||||
|
|
||||||
colorsTrackBy (index) {
|
colorsTrackBy (index) {
|
||||||
|
@@ -18,8 +18,8 @@ export class EditProfileModalComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit () {
|
ngOnInit () {
|
||||||
this.profile.sessionOptions.env = this.profile.sessionOptions.env || {}
|
this.profile.sessionOptions.env = this.profile.sessionOptions.env ?? {}
|
||||||
this.profile.sessionOptions.args = this.profile.sessionOptions.args || []
|
this.profile.sessionOptions.args = this.profile.sessionOptions.args ?? []
|
||||||
}
|
}
|
||||||
|
|
||||||
save () {
|
save () {
|
||||||
|
@@ -60,14 +60,12 @@ export class ShellSettingsTabComponent {
|
|||||||
properties: ['openDirectory', 'showHiddenFiles'],
|
properties: ['openDirectory', 'showHiddenFiles'],
|
||||||
}
|
}
|
||||||
)).filePaths
|
)).filePaths
|
||||||
if (paths) {
|
this.config.store.terminal.workingDirectory = paths[0]
|
||||||
this.config.store.terminal.workingDirectory = paths[0]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
newProfile (shell: Shell): void {
|
newProfile (shell: Shell): void {
|
||||||
const profile: Profile = {
|
const profile: Profile = {
|
||||||
name: shell.name || '',
|
name: shell.name ?? '',
|
||||||
shell: shell.id,
|
shell: shell.id,
|
||||||
sessionOptions: this.terminal.optionsFromShell(shell),
|
sessionOptions: this.terminal.optionsFromShell(shell),
|
||||||
}
|
}
|
||||||
|
@@ -53,7 +53,7 @@ export class TerminalTabComponent extends BaseTerminalTabComponent {
|
|||||||
|
|
||||||
initializeSession (columns: number, rows: number): void {
|
initializeSession (columns: number, rows: number): void {
|
||||||
this.sessions.addSession(
|
this.sessions.addSession(
|
||||||
this.session,
|
this.session!,
|
||||||
Object.assign({}, this.sessionOptions, {
|
Object.assign({}, this.sessionOptions, {
|
||||||
width: columns,
|
width: columns,
|
||||||
height: rows,
|
height: rows,
|
||||||
@@ -69,15 +69,15 @@ export class TerminalTabComponent extends BaseTerminalTabComponent {
|
|||||||
type: 'app:terminal-tab',
|
type: 'app:terminal-tab',
|
||||||
sessionOptions: {
|
sessionOptions: {
|
||||||
...this.sessionOptions,
|
...this.sessionOptions,
|
||||||
cwd: cwd || this.sessionOptions.cwd,
|
cwd: cwd ?? this.sessionOptions.cwd,
|
||||||
},
|
},
|
||||||
savedState: this.frontend?.saveState(),
|
savedState: this.frontend?.saveState(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async getCurrentProcess (): Promise<BaseTabProcess|null> {
|
async getCurrentProcess (): Promise<BaseTabProcess|null> {
|
||||||
const children = await this.session.getChildProcesses()
|
const children = await this.session?.getChildProcesses()
|
||||||
if (!children.length) {
|
if (!children?.length) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
@@ -86,8 +86,8 @@ export class TerminalTabComponent extends BaseTerminalTabComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async canClose (): Promise<boolean> {
|
async canClose (): Promise<boolean> {
|
||||||
const children = await this.session.getChildProcesses()
|
const children = await this.session?.getChildProcesses()
|
||||||
if (children.length === 0) {
|
if (!children?.length) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return (await this.electron.showMessageBox(
|
return (await this.electron.showMessageBox(
|
||||||
@@ -104,6 +104,6 @@ export class TerminalTabComponent extends BaseTerminalTabComponent {
|
|||||||
ngOnDestroy (): void {
|
ngOnDestroy (): void {
|
||||||
this.homeEndSubscription.unsubscribe()
|
this.homeEndSubscription.unsubscribe()
|
||||||
super.ngOnDestroy()
|
super.ngOnDestroy()
|
||||||
this.session.destroy()
|
this.session?.destroy()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -4,6 +4,7 @@ import { ConfigProvider, Platform } from 'terminus-core'
|
|||||||
export class TerminalConfigProvider extends ConfigProvider {
|
export class TerminalConfigProvider extends ConfigProvider {
|
||||||
defaults = {
|
defaults = {
|
||||||
hotkeys: {
|
hotkeys: {
|
||||||
|
'copy-current-path': [],
|
||||||
shell: {
|
shell: {
|
||||||
__nonStructural: true,
|
__nonStructural: true,
|
||||||
},
|
},
|
||||||
|
@@ -18,7 +18,7 @@ export class DebugDecorator extends TerminalDecorator {
|
|||||||
let sessionOutputBuffer = ''
|
let sessionOutputBuffer = ''
|
||||||
const bufferLength = 8192
|
const bufferLength = 8192
|
||||||
|
|
||||||
this.subscribeUntilDetached(terminal, terminal.session.output$.subscribe(data => {
|
this.subscribeUntilDetached(terminal, terminal.session!.output$.subscribe(data => {
|
||||||
sessionOutputBuffer += data
|
sessionOutputBuffer += data
|
||||||
if (sessionOutputBuffer.length > bufferLength) {
|
if (sessionOutputBuffer.length > bufferLength) {
|
||||||
sessionOutputBuffer = sessionOutputBuffer.substring(sessionOutputBuffer.length - bufferLength)
|
sessionOutputBuffer = sessionOutputBuffer.substring(sessionOutputBuffer.length - bufferLength)
|
||||||
@@ -88,18 +88,18 @@ export class DebugDecorator extends TerminalDecorator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private doSaveState (terminal: TerminalTabComponent) {
|
private doSaveState (terminal: TerminalTabComponent) {
|
||||||
this.saveFile(terminal.frontend.saveState(), 'state.txt')
|
this.saveFile(terminal.frontend!.saveState(), 'state.txt')
|
||||||
}
|
}
|
||||||
|
|
||||||
private async doCopyState (terminal: TerminalTabComponent) {
|
private async doCopyState (terminal: TerminalTabComponent) {
|
||||||
const data = '```' + JSON.stringify(terminal.frontend.saveState()) + '```'
|
const data = '```' + JSON.stringify(terminal.frontend!.saveState()) + '```'
|
||||||
this.electron.clipboard.writeText(data)
|
this.electron.clipboard.writeText(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
private async doLoadState (terminal: TerminalTabComponent) {
|
private async doLoadState (terminal: TerminalTabComponent) {
|
||||||
const data = await this.loadFile()
|
const data = await this.loadFile()
|
||||||
if (data) {
|
if (data) {
|
||||||
terminal.frontend.restoreState(data)
|
terminal.frontend!.restoreState(data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -109,7 +109,7 @@ export class DebugDecorator extends TerminalDecorator {
|
|||||||
if (data.startsWith('`')) {
|
if (data.startsWith('`')) {
|
||||||
data = data.substring(3, data.length - 3)
|
data = data.substring(3, data.length - 3)
|
||||||
}
|
}
|
||||||
terminal.frontend.restoreState(JSON.parse(data))
|
terminal.frontend!.restoreState(JSON.parse(data))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,7 +125,7 @@ export class DebugDecorator extends TerminalDecorator {
|
|||||||
private async doLoadOutput (terminal: TerminalTabComponent) {
|
private async doLoadOutput (terminal: TerminalTabComponent) {
|
||||||
const data = await this.loadFile()
|
const data = await this.loadFile()
|
||||||
if (data) {
|
if (data) {
|
||||||
terminal.frontend.write(data)
|
terminal.frontend?.write(data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -135,7 +135,7 @@ export class DebugDecorator extends TerminalDecorator {
|
|||||||
if (data.startsWith('`')) {
|
if (data.startsWith('`')) {
|
||||||
data = data.substring(3, data.length - 3)
|
data = data.substring(3, data.length - 3)
|
||||||
}
|
}
|
||||||
terminal.frontend.write(JSON.parse(data))
|
terminal.frontend?.write(JSON.parse(data))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -7,10 +7,10 @@ import { TerminalTabComponent } from '../components/terminalTab.component'
|
|||||||
export class PathDropDecorator extends TerminalDecorator {
|
export class PathDropDecorator extends TerminalDecorator {
|
||||||
attach (terminal: TerminalTabComponent): void {
|
attach (terminal: TerminalTabComponent): void {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.subscribeUntilDetached(terminal, terminal.frontend.dragOver$.subscribe(event => {
|
this.subscribeUntilDetached(terminal, terminal.frontend?.dragOver$.subscribe(event => {
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
}))
|
}))
|
||||||
this.subscribeUntilDetached(terminal, terminal.frontend.drop$.subscribe(event => {
|
this.subscribeUntilDetached(terminal, terminal.frontend?.drop$.subscribe((event: DragEvent) => {
|
||||||
for (const file of event.dataTransfer!.files as any) {
|
for (const file of event.dataTransfer!.files as any) {
|
||||||
this.injectPath(terminal, file.path)
|
this.injectPath(terminal, file.path)
|
||||||
}
|
}
|
||||||
|
@@ -36,7 +36,7 @@ export class ZModemDecorator extends TerminalDecorator {
|
|||||||
terminal.write(data)
|
terminal.write(data)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
sender: data => terminal.session.write(Buffer.from(data)),
|
sender: data => terminal.session!.write(Buffer.from(data)),
|
||||||
on_detect: async detection => {
|
on_detect: async detection => {
|
||||||
try {
|
try {
|
||||||
terminal.enablePassthrough = false
|
terminal.enablePassthrough = false
|
||||||
@@ -50,7 +50,7 @@ export class ZModemDecorator extends TerminalDecorator {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.subscribeUntilDetached(terminal, terminal.session.binaryOutput$.subscribe(data => {
|
this.subscribeUntilDetached(terminal, terminal.session!.binaryOutput$.subscribe(data => {
|
||||||
const chunkSize = 1024
|
const chunkSize = 1024
|
||||||
for (let i = 0; i <= Math.floor(data.length / chunkSize); i++) {
|
for (let i = 0; i <= Math.floor(data.length / chunkSize); i++) {
|
||||||
try {
|
try {
|
||||||
@@ -153,6 +153,7 @@ export class ZModemDecorator extends TerminalDecorator {
|
|||||||
this.cancelEvent.toPromise(),
|
this.cancelEvent.toPromise(),
|
||||||
])
|
])
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
||||||
if (canceled) {
|
if (canceled) {
|
||||||
this.showMessage(terminal, colors.bgRed.black(' Canceled ') + ' ' + details.name)
|
this.showMessage(terminal, colors.bgRed.black(' Canceled ') + ' ' + details.name)
|
||||||
} else {
|
} else {
|
||||||
@@ -207,6 +208,7 @@ export class ZModemDecorator extends TerminalDecorator {
|
|||||||
|
|
||||||
await xfer.end()
|
await xfer.end()
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
||||||
if (canceled) {
|
if (canceled) {
|
||||||
this.showMessage(terminal, colors.bgRed.black(' Canceled ') + ' ' + offer.name)
|
this.showMessage(terminal, colors.bgRed.black(' Canceled ') + ' ' + offer.name)
|
||||||
} else {
|
} else {
|
||||||
|
@@ -33,7 +33,7 @@ export class XTermFrontend extends Frontend {
|
|||||||
private search = new SearchAddon()
|
private search = new SearchAddon()
|
||||||
private fitAddon = new FitAddon()
|
private fitAddon = new FitAddon()
|
||||||
private serializeAddon = new SerializeAddon()
|
private serializeAddon = new SerializeAddon()
|
||||||
private ligaturesAddon: LigaturesAddon
|
private ligaturesAddon?: LigaturesAddon
|
||||||
private opened = false
|
private opened = false
|
||||||
|
|
||||||
constructor () {
|
constructor () {
|
||||||
@@ -298,7 +298,7 @@ export class XTermFrontend extends Frontend {
|
|||||||
html += this.getLineAsHTML(selection.startRow, selection.startColumn, selection.endColumn)
|
html += this.getLineAsHTML(selection.startRow, selection.startColumn, selection.endColumn)
|
||||||
} else {
|
} else {
|
||||||
html += this.getLineAsHTML(selection.startRow, selection.startColumn, this.xterm.cols)
|
html += this.getLineAsHTML(selection.startRow, selection.startColumn, this.xterm.cols)
|
||||||
for (let y = selection.startRow! + 1; y < selection.endRow; y++) {
|
for (let y = selection.startRow + 1; y < selection.endRow; y++) {
|
||||||
html += this.getLineAsHTML(y, 0, this.xterm.cols)
|
html += this.getLineAsHTML(y, 0, this.xterm.cols)
|
||||||
}
|
}
|
||||||
html += this.getLineAsHTML(selection.endRow, 0, selection.endColumn)
|
html += this.getLineAsHTML(selection.endRow, 0, selection.endColumn)
|
||||||
|
@@ -62,6 +62,10 @@ export class TerminalHotkeyProvider extends HotkeyProvider {
|
|||||||
id: 'ctrl-c',
|
id: 'ctrl-c',
|
||||||
name: 'Intelligent Ctrl-C (copy/abort)',
|
name: 'Intelligent Ctrl-C (copy/abort)',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
id: 'copy-current-path',
|
||||||
|
name: 'Copy current path',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
id: 'search',
|
id: 'search',
|
||||||
name: 'Search',
|
name: 'Search',
|
||||||
|
@@ -171,7 +171,7 @@ export default class TerminalModule { // eslint-disable-line @typescript-eslint/
|
|||||||
argv = argv.slice(1)
|
argv = argv.slice(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (require('yargs').parse(argv.slice(1))._[0] !== 'open'){
|
if (require('yargs/yargs')(argv.slice(1)).parse()._[0] !== 'open'){
|
||||||
app.ready$.subscribe(() => {
|
app.ready$.subscribe(() => {
|
||||||
terminal.openTab()
|
terminal.openTab()
|
||||||
})
|
})
|
||||||
@@ -194,6 +194,9 @@ export default class TerminalModule { // eslint-disable-line @typescript-eslint/
|
|||||||
})
|
})
|
||||||
|
|
||||||
hostApp.cliOpenDirectory$.subscribe(async directory => {
|
hostApp.cliOpenDirectory$.subscribe(async directory => {
|
||||||
|
if (directory.length > 1 && (directory.endsWith('/') || directory.endsWith('\\'))) {
|
||||||
|
directory = directory.substring(0, directory.length - 1)
|
||||||
|
}
|
||||||
if (await fs.exists(directory)) {
|
if (await fs.exists(directory)) {
|
||||||
if ((await fs.stat(directory)).isDirectory()) {
|
if ((await fs.stat(directory)).isDirectory()) {
|
||||||
terminal.openTab(undefined, directory)
|
terminal.openTab(undefined, directory)
|
||||||
|
@@ -7,7 +7,7 @@ import { TerminalTabComponent } from './components/terminalTab.component'
|
|||||||
@Injectable()
|
@Injectable()
|
||||||
export class RecoveryProvider extends TabRecoveryProvider {
|
export class RecoveryProvider extends TabRecoveryProvider {
|
||||||
async recover (recoveryToken: RecoveryToken): Promise<RecoveredTab|null> {
|
async recover (recoveryToken: RecoveryToken): Promise<RecoveredTab|null> {
|
||||||
if (recoveryToken?.type === 'app:terminal-tab') {
|
if (recoveryToken.type === 'app:terminal-tab') {
|
||||||
return {
|
return {
|
||||||
type: TerminalTabComponent,
|
type: TerminalTabComponent,
|
||||||
options: {
|
options: {
|
||||||
|
@@ -87,6 +87,7 @@ export abstract class BaseSession {
|
|||||||
abstract kill (signal?: string): void
|
abstract kill (signal?: string): void
|
||||||
abstract async getChildProcesses (): Promise<ChildProcess[]>
|
abstract async getChildProcesses (): Promise<ChildProcess[]>
|
||||||
abstract async gracefullyKillProcess (): Promise<void>
|
abstract async gracefullyKillProcess (): Promise<void>
|
||||||
|
abstract supportsWorkingDirectory (): boolean
|
||||||
abstract async getWorkingDirectory (): Promise<string|null>
|
abstract async getWorkingDirectory (): Promise<string|null>
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -102,7 +103,7 @@ export class Session extends BaseSession {
|
|||||||
}
|
}
|
||||||
|
|
||||||
start (options: SessionOptions): void {
|
start (options: SessionOptions): void {
|
||||||
this.name = options.name || ''
|
this.name = options.name ?? ''
|
||||||
|
|
||||||
const env = {
|
const env = {
|
||||||
...process.env,
|
...process.env,
|
||||||
@@ -113,7 +114,7 @@ export class Session extends BaseSession {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (process.platform === 'darwin' && !process.env.LC_ALL) {
|
if (process.platform === 'darwin' && !process.env.LC_ALL) {
|
||||||
const locale = process.env.LC_CTYPE || 'en_US.UTF-8'
|
const locale = process.env.LC_CTYPE ?? 'en_US.UTF-8'
|
||||||
Object.assign(env, {
|
Object.assign(env, {
|
||||||
LANG: locale,
|
LANG: locale,
|
||||||
LC_ALL: locale,
|
LC_ALL: locale,
|
||||||
@@ -124,17 +125,17 @@ export class Session extends BaseSession {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
let cwd = options.cwd || process.env.HOME
|
let cwd = options.cwd ?? process.env.HOME
|
||||||
|
|
||||||
if (!fs.existsSync(cwd)) {
|
if (!fs.existsSync(cwd)) {
|
||||||
console.warn('Ignoring non-existent CWD:', cwd)
|
console.warn('Ignoring non-existent CWD:', cwd)
|
||||||
cwd = undefined
|
cwd = undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
this.pty = nodePTY.spawn(options.command, options.args || [], {
|
this.pty = nodePTY.spawn(options.command, options.args ?? [], {
|
||||||
name: 'xterm-256color',
|
name: 'xterm-256color',
|
||||||
cols: options.width || 80,
|
cols: options.width ?? 80,
|
||||||
rows: options.height || 30,
|
rows: options.height ?? 30,
|
||||||
encoding: null,
|
encoding: null,
|
||||||
cwd,
|
cwd,
|
||||||
env: env,
|
env: env,
|
||||||
@@ -142,7 +143,7 @@ export class Session extends BaseSession {
|
|||||||
useConpty: (isWindowsBuild(WIN_BUILD_CONPTY_SUPPORTED) && this.config.store.terminal.useConPTY ? 1 : false) as any,
|
useConpty: (isWindowsBuild(WIN_BUILD_CONPTY_SUPPORTED) && this.config.store.terminal.useConPTY ? 1 : false) as any,
|
||||||
})
|
})
|
||||||
|
|
||||||
this.guessedCWD = cwd || null
|
this.guessedCWD = cwd ?? null
|
||||||
|
|
||||||
this.truePID = this.pty['pid']
|
this.truePID = this.pty['pid']
|
||||||
|
|
||||||
@@ -181,7 +182,7 @@ export class Session extends BaseSession {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
this.pauseAfterExit = options.pauseAfterExit || false
|
this.pauseAfterExit = options.pauseAfterExit ?? false
|
||||||
}
|
}
|
||||||
|
|
||||||
resize (columns: number, rows: number): void {
|
resize (columns: number, rows: number): void {
|
||||||
@@ -259,6 +260,16 @@ export class Session extends BaseSession {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
supportsWorkingDirectory (): boolean {
|
||||||
|
if (this.reportedCWD || this.guessedCWD) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if (!this.truePID) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return process.platform !== 'win32'
|
||||||
|
}
|
||||||
|
|
||||||
async getWorkingDirectory (): Promise<string|null> {
|
async getWorkingDirectory (): Promise<string|null> {
|
||||||
if (this.reportedCWD) {
|
if (this.reportedCWD) {
|
||||||
return this.reportedCWD
|
return this.reportedCWD
|
||||||
@@ -331,7 +342,7 @@ export class Session extends BaseSession {
|
|||||||
/** @hidden */
|
/** @hidden */
|
||||||
@Injectable({ providedIn: 'root' })
|
@Injectable({ providedIn: 'root' })
|
||||||
export class SessionsService {
|
export class SessionsService {
|
||||||
sessions: Record<string, BaseSession> = {}
|
sessions = new Map<string, BaseSession>()
|
||||||
logger: Logger
|
logger: Logger
|
||||||
private lastID = 0
|
private lastID = 0
|
||||||
|
|
||||||
@@ -347,9 +358,9 @@ export class SessionsService {
|
|||||||
options.name = `session-${this.lastID}`
|
options.name = `session-${this.lastID}`
|
||||||
session.start(options)
|
session.start(options)
|
||||||
session.destroyed$.pipe(first()).subscribe(() => {
|
session.destroyed$.pipe(first()).subscribe(() => {
|
||||||
delete this.sessions[session.name]
|
this.sessions.delete(session.name)
|
||||||
})
|
})
|
||||||
this.sessions[session.name] = session
|
this.sessions.set(session.name, session)
|
||||||
return session
|
return session
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -38,6 +38,7 @@ export class TerminalService {
|
|||||||
const shells = await this.shells$.toPromise()
|
const shells = await this.shells$.toPromise()
|
||||||
return [
|
return [
|
||||||
...this.config.store.terminal.profiles,
|
...this.config.store.terminal.profiles,
|
||||||
|
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
|
||||||
...skipDefault ? [] : shells.filter(x => includeHidden || !x.hidden).map(shell => ({
|
...skipDefault ? [] : shells.filter(x => includeHidden || !x.hidden).map(shell => ({
|
||||||
name: shell.name,
|
name: shell.name,
|
||||||
shell: shell.id,
|
shell: shell.id,
|
||||||
@@ -52,16 +53,16 @@ export class TerminalService {
|
|||||||
return slugify(profile.name, { remove: /[:.]/g }).toLowerCase()
|
return slugify(profile.name, { remove: /[:.]/g }).toLowerCase()
|
||||||
}
|
}
|
||||||
|
|
||||||
async getProfileByID (id: string): Promise<Profile> {
|
async getProfileByID (id: string): Promise<Profile|null> {
|
||||||
const profiles = await this.getProfiles({ includeHidden: true })
|
const profiles = await this.getProfiles({ includeHidden: true })
|
||||||
return profiles.find(x => this.getProfileID(x) === id) || profiles[0]
|
return profiles.find(x => this.getProfileID(x) === id) ?? null
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Launches a new terminal with a specific shell and CWD
|
* Launches a new terminal with a specific shell and CWD
|
||||||
* @param pause Wait for a keypress when the shell exits
|
* @param pause Wait for a keypress when the shell exits
|
||||||
*/
|
*/
|
||||||
async openTab (profile?: Profile, cwd?: string|null, pause?: boolean): Promise<TerminalTabComponent> {
|
async openTab (profile?: Profile|null, cwd?: string|null, pause?: boolean): Promise<TerminalTabComponent> {
|
||||||
if (!profile) {
|
if (!profile) {
|
||||||
profile = await this.getProfileByID(this.config.store.terminal.profile)
|
profile = await this.getProfileByID(this.config.store.terminal.profile)
|
||||||
if (!profile) {
|
if (!profile) {
|
||||||
@@ -69,7 +70,7 @@ export class TerminalService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cwd = cwd || profile.sessionOptions.cwd
|
cwd = cwd ?? profile.sessionOptions.cwd
|
||||||
|
|
||||||
if (cwd && !fs.existsSync(cwd)) {
|
if (cwd && !fs.existsSync(cwd)) {
|
||||||
console.warn('Ignoring non-existent CWD:', cwd)
|
console.warn('Ignoring non-existent CWD:', cwd)
|
||||||
@@ -89,20 +90,19 @@ export class TerminalService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cwd = cwd || this.config.store.terminal.workingDirectory
|
cwd = cwd ?? this.config.store.terminal.workingDirectory
|
||||||
cwd = cwd || null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.logger.info(`Starting profile ${profile.name}`, profile)
|
this.logger.info(`Starting profile ${profile.name}`, profile)
|
||||||
const sessionOptions = {
|
const sessionOptions = {
|
||||||
...profile.sessionOptions,
|
...profile.sessionOptions,
|
||||||
pauseAfterExit: pause,
|
pauseAfterExit: pause,
|
||||||
cwd: cwd || undefined,
|
cwd: cwd ?? undefined,
|
||||||
}
|
}
|
||||||
|
|
||||||
const tab = this.openTabWithOptions(sessionOptions)
|
const tab = this.openTabWithOptions(sessionOptions)
|
||||||
if (profile?.color) {
|
if (profile.color) {
|
||||||
(this.app.getParentTab(tab) || tab).color = profile.color
|
(this.app.getParentTab(tab) ?? tab).color = profile.color
|
||||||
}
|
}
|
||||||
return tab
|
return tab
|
||||||
}
|
}
|
||||||
@@ -110,7 +110,7 @@ export class TerminalService {
|
|||||||
optionsFromShell (shell: Shell): SessionOptions {
|
optionsFromShell (shell: Shell): SessionOptions {
|
||||||
return {
|
return {
|
||||||
command: shell.command,
|
command: shell.command,
|
||||||
args: shell.args || [],
|
args: shell.args ?? [],
|
||||||
env: shell.env,
|
env: shell.env,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -32,7 +32,7 @@ export class UACService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const options = { ...sessionOptions }
|
const options = { ...sessionOptions }
|
||||||
options.args = [options.command, ...options.args]
|
options.args = [options.command, ...options.args ?? []]
|
||||||
options.command = helperPath
|
options.command = helperPath
|
||||||
return options
|
return options
|
||||||
}
|
}
|
||||||
|
@@ -30,7 +30,7 @@ export class SaveAsProfileContextMenu extends TabContextMenuItemProvider {
|
|||||||
const profile = {
|
const profile = {
|
||||||
sessionOptions: {
|
sessionOptions: {
|
||||||
...tab.sessionOptions,
|
...tab.sessionOptions,
|
||||||
cwd: await tab.session.getWorkingDirectory() || tab.sessionOptions.cwd,
|
cwd: await tab.session?.getWorkingDirectory() ?? tab.sessionOptions.cwd,
|
||||||
},
|
},
|
||||||
name: tab.sessionOptions.command,
|
name: tab.sessionOptions.command,
|
||||||
}
|
}
|
||||||
@@ -79,7 +79,7 @@ export class NewTabContextMenu extends TabContextMenuItemProvider {
|
|||||||
click: () => this.zone.run(async () => {
|
click: () => this.zone.run(async () => {
|
||||||
let workingDirectory = this.config.store.terminal.workingDirectory
|
let workingDirectory = this.config.store.terminal.workingDirectory
|
||||||
if (this.config.store.terminal.alwaysUseWorkingDirectory !== true && tab instanceof TerminalTabComponent) {
|
if (this.config.store.terminal.alwaysUseWorkingDirectory !== true && tab instanceof TerminalTabComponent) {
|
||||||
workingDirectory = await tab.session.getWorkingDirectory()
|
workingDirectory = await tab.session?.getWorkingDirectory()
|
||||||
}
|
}
|
||||||
await this.terminalService.openTab(profile, workingDirectory)
|
await this.terminalService.openTab(profile, workingDirectory)
|
||||||
}),
|
}),
|
||||||
@@ -123,6 +123,13 @@ export class NewTabContextMenu extends TabContextMenuItemProvider {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (tab instanceof TerminalTabComponent && tab.session?.supportsWorkingDirectory()) {
|
||||||
|
items.push({
|
||||||
|
label: 'Copy current path',
|
||||||
|
click: () => this.zone.run(() => tab.copyCurrentPath()),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
return items
|
return items
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -150,7 +157,7 @@ export class CopyPasteContextMenu extends TabContextMenuItemProvider {
|
|||||||
click: (): void => {
|
click: (): void => {
|
||||||
this.zone.run(() => {
|
this.zone.run(() => {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
tab.frontend.copySelection()
|
tab.frontend?.copySelection()
|
||||||
this.toastr.info('Copied')
|
this.toastr.info('Copied')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -174,7 +181,7 @@ export class LegacyContextMenu extends TabContextMenuItemProvider {
|
|||||||
weight = 1
|
weight = 1
|
||||||
|
|
||||||
constructor (
|
constructor (
|
||||||
@Optional() @Inject(TerminalContextMenuItemProvider) protected contextMenuProviders: TerminalContextMenuItemProvider[],
|
@Optional() @Inject(TerminalContextMenuItemProvider) protected contextMenuProviders: TerminalContextMenuItemProvider[]|null,
|
||||||
) {
|
) {
|
||||||
super()
|
super()
|
||||||
}
|
}
|
||||||
|
@@ -74,4 +74,6 @@ module.exports = {
|
|||||||
'ngx-toastr',
|
'ngx-toastr',
|
||||||
/^terminus-/,
|
/^terminus-/,
|
||||||
],
|
],
|
||||||
|
// Ignore warnings due to yarg's dynamic module loading
|
||||||
|
ignoreWarnings: [/node_modules\/yargs/],
|
||||||
}
|
}
|
||||||
|
365
yarn.lock
365
yarn.lock
@@ -52,6 +52,17 @@
|
|||||||
global-agent "^2.0.2"
|
global-agent "^2.0.2"
|
||||||
global-tunnel-ng "^2.7.1"
|
global-tunnel-ng "^2.7.1"
|
||||||
|
|
||||||
|
"@electron/universal@1.0.4":
|
||||||
|
version "1.0.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/@electron/universal/-/universal-1.0.4.tgz#231ac246c39d45b80e159bd21c3f9027dcaa10f5"
|
||||||
|
integrity sha512-ajZoumi4XwqwmZe8YVhu4XGkZBCPyWZsVCQONPTIe9TUlleSN+dic3YpXlaWcilx/HOzTdldTKtabNTeI0gDoA==
|
||||||
|
dependencies:
|
||||||
|
"@malept/cross-spawn-promise" "^1.1.0"
|
||||||
|
asar "^3.0.3"
|
||||||
|
debug "^4.3.1"
|
||||||
|
dir-compare "^2.4.0"
|
||||||
|
fs-extra "^9.0.1"
|
||||||
|
|
||||||
"@eslint/eslintrc@^0.2.2":
|
"@eslint/eslintrc@^0.2.2":
|
||||||
version "0.2.2"
|
version "0.2.2"
|
||||||
resolved "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.2.2.tgz"
|
resolved "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.2.2.tgz"
|
||||||
@@ -348,10 +359,10 @@
|
|||||||
resolved "https://registry.npmjs.org/@types/node/-/node-14.14.14.tgz"
|
resolved "https://registry.npmjs.org/@types/node/-/node-14.14.14.tgz"
|
||||||
integrity sha512-UHnOPWVWV1z+VV8k6L1HhG7UbGBgIdghqF3l9Ny9ApPghbjICXkUJSd/b9gOgQfjM1r+37cipdw/HJ3F6ICEnQ==
|
integrity sha512-UHnOPWVWV1z+VV8k6L1HhG7UbGBgIdghqF3l9Ny9ApPghbjICXkUJSd/b9gOgQfjM1r+37cipdw/HJ3F6ICEnQ==
|
||||||
|
|
||||||
"@types/node@^12.0.12":
|
"@types/node@^14.6.2":
|
||||||
version "12.19.9"
|
version "14.14.22"
|
||||||
resolved "https://registry.npmjs.org/@types/node/-/node-12.19.9.tgz"
|
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.22.tgz#0d29f382472c4ccf3bd96ff0ce47daf5b7b84b18"
|
||||||
integrity sha512-yj0DOaQeUrk3nJ0bd3Y5PeDRJ6W0r+kilosLA+dzF3dola/o9hxhMSg2sFvVcA2UHS5JSOsZp4S0c1OEXc4m1Q==
|
integrity sha512-g+f/qj/cNcqKkc3tFqlXOYjrmZA+jNBiDzbP3kH+B+otKFqAdPgVTGP1IeKRdMml/aE69as5S4FqtxAbl+LaMw==
|
||||||
|
|
||||||
"@types/plist@^3.0.1":
|
"@types/plist@^3.0.1":
|
||||||
version "3.0.2"
|
version "3.0.2"
|
||||||
@@ -383,9 +394,9 @@
|
|||||||
resolved "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-15.0.0.tgz"
|
resolved "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-15.0.0.tgz"
|
||||||
integrity sha512-FA/BWv8t8ZWJ+gEOnLLd8ygxH/2UFbAvgEonyfN6yWGLKc7zVjbpl2Y4CTjid9h2RfgPP6SEt6uHwEOply00yw==
|
integrity sha512-FA/BWv8t8ZWJ+gEOnLLd8ygxH/2UFbAvgEonyfN6yWGLKc7zVjbpl2Y4CTjid9h2RfgPP6SEt6uHwEOply00yw==
|
||||||
|
|
||||||
"@types/yargs@^15.0.11":
|
"@types/yargs@^15.0.12":
|
||||||
version "15.0.12"
|
version "15.0.12"
|
||||||
resolved "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.12.tgz"
|
resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-15.0.12.tgz#6234ce3e3e3fa32c5db301a170f96a599c960d74"
|
||||||
integrity sha512-f+fD/fQAo3BCbCDlrUpznF1A5Zp9rB0noS5vnoormHSIPFKL0Z2DcUJ3Gxp5ytH4uLRNxy7AwYUC9exZzqGMAw==
|
integrity sha512-f+fD/fQAo3BCbCDlrUpznF1A5Zp9rB0noS5vnoormHSIPFKL0Z2DcUJ3Gxp5ytH4uLRNxy7AwYUC9exZzqGMAw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@types/yargs-parser" "*"
|
"@types/yargs-parser" "*"
|
||||||
@@ -678,9 +689,9 @@ acorn@^8.0.4:
|
|||||||
integrity sha512-XNP0PqF1XD19ZlLKvB7cMmnZswW4C/03pRHgirB30uSJTaS3A3V1/P4sS3HPvFmjoriPCJQs+JDSbm4bL1TxGQ==
|
integrity sha512-XNP0PqF1XD19ZlLKvB7cMmnZswW4C/03pRHgirB30uSJTaS3A3V1/P4sS3HPvFmjoriPCJQs+JDSbm4bL1TxGQ==
|
||||||
|
|
||||||
agent-base@4, agent-base@^4.0.1, agent-base@^4.1.0:
|
agent-base@4, agent-base@^4.0.1, agent-base@^4.1.0:
|
||||||
version "4.1.0"
|
version "4.3.0"
|
||||||
resolved "https://registry.npmjs.org/agent-base/-/agent-base-4.1.0.tgz"
|
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.3.0.tgz#8165f01c436009bccad0b1d122f05ed770efc6ee"
|
||||||
integrity sha1-IOF0Ac1Js8B2v1akvGxbQ2/6jVU=
|
integrity sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==
|
||||||
dependencies:
|
dependencies:
|
||||||
es6-promisify "^5.0.0"
|
es6-promisify "^5.0.0"
|
||||||
|
|
||||||
@@ -803,26 +814,27 @@ ansistyles@~0.1.3:
|
|||||||
resolved "https://registry.npmjs.org/ansistyles/-/ansistyles-0.1.3.tgz"
|
resolved "https://registry.npmjs.org/ansistyles/-/ansistyles-0.1.3.tgz"
|
||||||
integrity sha1-XeYEFb2gcbs3EnhUyGT0GyMlRTk=
|
integrity sha1-XeYEFb2gcbs3EnhUyGT0GyMlRTk=
|
||||||
|
|
||||||
app-builder-bin@3.5.10:
|
app-builder-bin@3.5.12:
|
||||||
version "3.5.10"
|
version "3.5.12"
|
||||||
resolved "https://registry.npmjs.org/app-builder-bin/-/app-builder-bin-3.5.10.tgz"
|
resolved "https://registry.yarnpkg.com/app-builder-bin/-/app-builder-bin-3.5.12.tgz#bbe174972cc1f481f73d6d92ad47a8b4c7eb4530"
|
||||||
integrity sha512-Jd+GW68lR0NeetgZDo47PdWBEPdnD+p0jEa7XaxjRC8u6Oo/wgJsfKUkORRgr2NpkD19IFKN50P6JYy04XHFLQ==
|
integrity sha512-lQARM2AielmFoBeIo6LZigAe+58Wwe07ZWkt+wVeDxzyieNmeWjlvz/V5dKzinydwdHd+CNswN86sww46yijjA==
|
||||||
|
|
||||||
app-builder-lib@22.10.3:
|
app-builder-lib@22.10.4:
|
||||||
version "22.10.3"
|
version "22.10.4"
|
||||||
resolved "https://registry.npmjs.org/app-builder-lib/-/app-builder-lib-22.10.3.tgz"
|
resolved "https://registry.yarnpkg.com/app-builder-lib/-/app-builder-lib-22.10.4.tgz#3fc70821b76beb9c8279d9de22960ef2174da153"
|
||||||
integrity sha512-PBHTTGxV1uLVHWKQfw92plrfMo/utH0FVe8v2dFmT/CYKw9u7XuOC0xE8YslUxXmaiG6TuOJaQrII4fXN5VBpQ==
|
integrity sha512-q7B1cr8Ry4a7o08EKShLfwsnIVf5By7YhVwcoqgEwPKxtoj1qF0kB4wyBP79rJylYi0Zj2cSkJJ/gD/ef9xhoQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
"7zip-bin" "~5.0.3"
|
"7zip-bin" "~5.0.3"
|
||||||
"@develar/schema-utils" "~2.6.5"
|
"@develar/schema-utils" "~2.6.5"
|
||||||
|
"@electron/universal" "1.0.4"
|
||||||
async-exit-hook "^2.0.1"
|
async-exit-hook "^2.0.1"
|
||||||
bluebird-lst "^1.0.9"
|
bluebird-lst "^1.0.9"
|
||||||
builder-util "22.10.3"
|
builder-util "22.10.4"
|
||||||
builder-util-runtime "8.7.3"
|
builder-util-runtime "8.7.3"
|
||||||
chromium-pickle-js "^0.2.0"
|
chromium-pickle-js "^0.2.0"
|
||||||
debug "^4.3.2"
|
debug "^4.3.1"
|
||||||
ejs "^3.1.5"
|
ejs "^3.1.5"
|
||||||
electron-publish "22.10.3"
|
electron-publish "22.10.4"
|
||||||
fs-extra "^9.0.1"
|
fs-extra "^9.0.1"
|
||||||
hosted-git-info "^3.0.7"
|
hosted-git-info "^3.0.7"
|
||||||
is-ci "^2.0.0"
|
is-ci "^2.0.0"
|
||||||
@@ -938,7 +950,7 @@ asap@~2.0.3:
|
|||||||
resolved "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz"
|
resolved "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz"
|
||||||
integrity sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=
|
integrity sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=
|
||||||
|
|
||||||
asar@^3.0.0:
|
asar@^3.0.0, asar@^3.0.3:
|
||||||
version "3.0.3"
|
version "3.0.3"
|
||||||
resolved "https://registry.npmjs.org/asar/-/asar-3.0.3.tgz"
|
resolved "https://registry.npmjs.org/asar/-/asar-3.0.3.tgz"
|
||||||
integrity sha512-k7zd+KoR+n8pl71PvgElcoKHrVNiSXtw7odKbyNpmgKe7EGRF9Pnu3uLOukD37EvavKwVFxOUpqXTIZC5B5Pmw==
|
integrity sha512-k7zd+KoR+n8pl71PvgElcoKHrVNiSXtw7odKbyNpmgKe7EGRF9Pnu3uLOukD37EvavKwVFxOUpqXTIZC5B5Pmw==
|
||||||
@@ -1076,7 +1088,7 @@ babylon@^6.18.0:
|
|||||||
|
|
||||||
balanced-match@^1.0.0:
|
balanced-match@^1.0.0:
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz"
|
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
|
||||||
integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c=
|
integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c=
|
||||||
|
|
||||||
base64-js@^1.2.3, base64-js@^1.3.1:
|
base64-js@^1.2.3, base64-js@^1.3.1:
|
||||||
@@ -1200,7 +1212,7 @@ boxen@^4.2.0:
|
|||||||
|
|
||||||
brace-expansion@^1.1.7:
|
brace-expansion@^1.1.7:
|
||||||
version "1.1.11"
|
version "1.1.11"
|
||||||
resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz"
|
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
|
||||||
integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==
|
integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==
|
||||||
dependencies:
|
dependencies:
|
||||||
balanced-match "^1.0.0"
|
balanced-match "^1.0.0"
|
||||||
@@ -1240,11 +1252,34 @@ browserslist@^4.14.5:
|
|||||||
escalade "^3.1.1"
|
escalade "^3.1.1"
|
||||||
node-releases "^1.1.67"
|
node-releases "^1.1.67"
|
||||||
|
|
||||||
|
buffer-alloc-unsafe@^1.1.0:
|
||||||
|
version "1.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0"
|
||||||
|
integrity sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==
|
||||||
|
|
||||||
|
buffer-alloc@^1.2.0:
|
||||||
|
version "1.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/buffer-alloc/-/buffer-alloc-1.2.0.tgz#890dd90d923a873e08e10e5fd51a57e5b7cce0ec"
|
||||||
|
integrity sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==
|
||||||
|
dependencies:
|
||||||
|
buffer-alloc-unsafe "^1.1.0"
|
||||||
|
buffer-fill "^1.0.0"
|
||||||
|
|
||||||
buffer-crc32@~0.2.3:
|
buffer-crc32@~0.2.3:
|
||||||
version "0.2.13"
|
version "0.2.13"
|
||||||
resolved "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz"
|
resolved "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz"
|
||||||
integrity sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=
|
integrity sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=
|
||||||
|
|
||||||
|
buffer-equal@1.0.0:
|
||||||
|
version "1.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/buffer-equal/-/buffer-equal-1.0.0.tgz#59616b498304d556abd466966b22eeda3eca5fbe"
|
||||||
|
integrity sha1-WWFrSYME1Var1GaWayLu2j7KX74=
|
||||||
|
|
||||||
|
buffer-fill@^1.0.0:
|
||||||
|
version "1.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-1.0.0.tgz#f8f78b76789888ef39f205cd637f68e702122b2c"
|
||||||
|
integrity sha1-+PeLdniYiO858gXNY39o5wISKyw=
|
||||||
|
|
||||||
buffer-from@^1.0.0:
|
buffer-from@^1.0.0:
|
||||||
version "1.1.1"
|
version "1.1.1"
|
||||||
resolved "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz"
|
resolved "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz"
|
||||||
@@ -1266,19 +1301,19 @@ builder-util-runtime@8.7.3:
|
|||||||
debug "^4.3.2"
|
debug "^4.3.2"
|
||||||
sax "^1.2.4"
|
sax "^1.2.4"
|
||||||
|
|
||||||
builder-util@22.10.3:
|
builder-util@22.10.4:
|
||||||
version "22.10.3"
|
version "22.10.4"
|
||||||
resolved "https://registry.npmjs.org/builder-util/-/builder-util-22.10.3.tgz"
|
resolved "https://registry.yarnpkg.com/builder-util/-/builder-util-22.10.4.tgz#54e8be83dd0dec28073d866ff087cee8e7ce6cf6"
|
||||||
integrity sha512-I9mh78wZaggIF4QkBzMPKhfgGDameyx9TN6Zikl8SKQHiKQNCUzMPUcRXCyCot6iTT8B8blwOM3GhhuU06yv1g==
|
integrity sha512-XdcbFG3otEkNRKxW2wS1npNviCb/IrzusEQ55lMB+6YEHxBOfTbf8vnPt0pDumfwmxls9xczABU+mfqN/W4uDw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"7zip-bin" "~5.0.3"
|
"7zip-bin" "~5.0.3"
|
||||||
"@types/debug" "^4.1.5"
|
"@types/debug" "^4.1.5"
|
||||||
"@types/fs-extra" "^9.0.5"
|
"@types/fs-extra" "^9.0.5"
|
||||||
app-builder-bin "3.5.10"
|
app-builder-bin "3.5.12"
|
||||||
bluebird-lst "^1.0.9"
|
bluebird-lst "^1.0.9"
|
||||||
builder-util-runtime "8.7.3"
|
builder-util-runtime "8.7.3"
|
||||||
chalk "^4.1.0"
|
chalk "^4.1.0"
|
||||||
debug "^4.3.2"
|
debug "^4.3.1"
|
||||||
fs-extra "^9.0.1"
|
fs-extra "^9.0.1"
|
||||||
is-ci "^2.0.0"
|
is-ci "^2.0.0"
|
||||||
js-yaml "^3.14.1"
|
js-yaml "^3.14.1"
|
||||||
@@ -1481,12 +1516,7 @@ character-parser@^2.1.1:
|
|||||||
dependencies:
|
dependencies:
|
||||||
is-regex "^1.0.3"
|
is-regex "^1.0.3"
|
||||||
|
|
||||||
chownr@^1.0.1, chownr@~1.0.1:
|
chownr@^1.0.1, chownr@^1.1.1:
|
||||||
version "1.0.1"
|
|
||||||
resolved "https://registry.npmjs.org/chownr/-/chownr-1.0.1.tgz"
|
|
||||||
integrity sha1-4qdQQqlVGQi+vSW4Uj1fl2nXkYE=
|
|
||||||
|
|
||||||
chownr@^1.1.1:
|
|
||||||
version "1.1.4"
|
version "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==
|
||||||
@@ -1496,6 +1526,11 @@ chownr@^2.0.0:
|
|||||||
resolved "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz"
|
resolved "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz"
|
||||||
integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==
|
integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==
|
||||||
|
|
||||||
|
chownr@~1.0.1:
|
||||||
|
version "1.0.1"
|
||||||
|
resolved "https://registry.npmjs.org/chownr/-/chownr-1.0.1.tgz"
|
||||||
|
integrity sha1-4qdQQqlVGQi+vSW4Uj1fl2nXkYE=
|
||||||
|
|
||||||
chrome-trace-event@^1.0.2:
|
chrome-trace-event@^1.0.2:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
resolved "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz"
|
resolved "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz"
|
||||||
@@ -1677,6 +1712,11 @@ colorette@^1.2.1:
|
|||||||
resolved "https://registry.npmjs.org/colorette/-/colorette-1.2.1.tgz"
|
resolved "https://registry.npmjs.org/colorette/-/colorette-1.2.1.tgz"
|
||||||
integrity sha512-puCDz0CzydiSYOrnXpz/PKd69zRrribezjtE9yd4zvytoRc8+RY/KJPvtPFKZS3E3wP6neGyMe0vOTlHO5L3Pw==
|
integrity sha512-puCDz0CzydiSYOrnXpz/PKd69zRrribezjtE9yd4zvytoRc8+RY/KJPvtPFKZS3E3wP6neGyMe0vOTlHO5L3Pw==
|
||||||
|
|
||||||
|
colors@1.0.3:
|
||||||
|
version "1.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/colors/-/colors-1.0.3.tgz#0433f44d809680fdeb60ed260f1b0c262e82a40b"
|
||||||
|
integrity sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=
|
||||||
|
|
||||||
colors@^1.3.3:
|
colors@^1.3.3:
|
||||||
version "1.4.0"
|
version "1.4.0"
|
||||||
resolved "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz"
|
resolved "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz"
|
||||||
@@ -1719,6 +1759,13 @@ commander@2.17.x:
|
|||||||
resolved "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz"
|
resolved "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz"
|
||||||
integrity sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==
|
integrity sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==
|
||||||
|
|
||||||
|
commander@2.9.0:
|
||||||
|
version "2.9.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4"
|
||||||
|
integrity sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=
|
||||||
|
dependencies:
|
||||||
|
graceful-readlink ">= 1.0.0"
|
||||||
|
|
||||||
commander@^2.20.0, commander@^2.9.0:
|
commander@^2.20.0, commander@^2.9.0:
|
||||||
version "2.20.3"
|
version "2.20.3"
|
||||||
resolved "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz"
|
resolved "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz"
|
||||||
@@ -1739,6 +1786,11 @@ commander@~2.19.0:
|
|||||||
resolved "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz"
|
resolved "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz"
|
||||||
integrity sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==
|
integrity sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==
|
||||||
|
|
||||||
|
compare-versions@^3.6.0:
|
||||||
|
version "3.6.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/compare-versions/-/compare-versions-3.6.0.tgz#1a5689913685e5a87637b8d3ffca75514ec41d62"
|
||||||
|
integrity sha512-W6Af2Iw1z4CB7q4uU4hv646dW9GQuBM+YpC0UvUCWSD8w90SJjp+ujJuXaEMtAXBtSqGfMPuFOVn4/+FlaqfBA==
|
||||||
|
|
||||||
component-emitter@^1.2.1:
|
component-emitter@^1.2.1:
|
||||||
version "1.3.0"
|
version "1.3.0"
|
||||||
resolved "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz"
|
resolved "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz"
|
||||||
@@ -1746,7 +1798,7 @@ component-emitter@^1.2.1:
|
|||||||
|
|
||||||
concat-map@0.0.1:
|
concat-map@0.0.1:
|
||||||
version "0.0.1"
|
version "0.0.1"
|
||||||
resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz"
|
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
|
||||||
integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=
|
integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=
|
||||||
|
|
||||||
concat-stream@^1.5.0, concat-stream@^1.5.2:
|
concat-stream@^1.5.0, concat-stream@^1.5.2:
|
||||||
@@ -2006,20 +2058,27 @@ dashdash@^1.12.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
assert-plus "^1.0.0"
|
assert-plus "^1.0.0"
|
||||||
|
|
||||||
debug@2, debug@^2.1.3, debug@^2.2.0, debug@^2.3.3, debug@^2.4.1, debug@^2.6.9:
|
debug@3.1.0:
|
||||||
version "2.6.9"
|
version "3.1.0"
|
||||||
resolved "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz"
|
resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
|
||||||
integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==
|
integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==
|
||||||
dependencies:
|
dependencies:
|
||||||
ms "2.0.0"
|
ms "2.0.0"
|
||||||
|
|
||||||
debug@4, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.2:
|
debug@4, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2:
|
||||||
version "4.3.2"
|
version "4.3.2"
|
||||||
resolved "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz"
|
resolved "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz"
|
||||||
integrity sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==
|
integrity sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==
|
||||||
dependencies:
|
dependencies:
|
||||||
ms "2.1.2"
|
ms "2.1.2"
|
||||||
|
|
||||||
|
debug@^2.1.3, debug@^2.2.0, debug@^2.3.3, debug@^2.4.1, debug@^2.6.9:
|
||||||
|
version "2.6.9"
|
||||||
|
resolved "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz"
|
||||||
|
integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==
|
||||||
|
dependencies:
|
||||||
|
ms "2.0.0"
|
||||||
|
|
||||||
debug@^3.0.0, debug@^3.2.6:
|
debug@^3.0.0, debug@^3.2.6:
|
||||||
version "3.2.7"
|
version "3.2.7"
|
||||||
resolved "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz"
|
resolved "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz"
|
||||||
@@ -2145,6 +2204,16 @@ dezalgo@^1.0.0, dezalgo@~1.0.3:
|
|||||||
asap "^2.0.0"
|
asap "^2.0.0"
|
||||||
wrappy "1"
|
wrappy "1"
|
||||||
|
|
||||||
|
dir-compare@^2.4.0:
|
||||||
|
version "2.4.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/dir-compare/-/dir-compare-2.4.0.tgz#785c41dc5f645b34343a4eafc50b79bac7f11631"
|
||||||
|
integrity sha512-l9hmu8x/rjVC9Z2zmGzkhOEowZvW7pmYws5CWHutg8u1JgvsKWMx7Q/UODeu4djLZ4FgW5besw5yvMQnBHzuCA==
|
||||||
|
dependencies:
|
||||||
|
buffer-equal "1.0.0"
|
||||||
|
colors "1.0.3"
|
||||||
|
commander "2.9.0"
|
||||||
|
minimatch "3.0.4"
|
||||||
|
|
||||||
dir-glob@^3.0.1:
|
dir-glob@^3.0.1:
|
||||||
version "3.0.1"
|
version "3.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f"
|
resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f"
|
||||||
@@ -2152,13 +2221,13 @@ dir-glob@^3.0.1:
|
|||||||
dependencies:
|
dependencies:
|
||||||
path-type "^4.0.0"
|
path-type "^4.0.0"
|
||||||
|
|
||||||
dmg-builder@22.10.3:
|
dmg-builder@22.10.4:
|
||||||
version "22.10.3"
|
version "22.10.4"
|
||||||
resolved "https://registry.npmjs.org/dmg-builder/-/dmg-builder-22.10.3.tgz"
|
resolved "https://registry.yarnpkg.com/dmg-builder/-/dmg-builder-22.10.4.tgz#8dab30754346791eb728091359558fd4a8dbb45f"
|
||||||
integrity sha512-OB0etdtZJrvx85ah1aoTv5zJ9CXlsepLs9VT6ax6FXxH9aGxJU38AuB8065OPTrj+btMuHQDd0kBVlcs4/BwpA==
|
integrity sha512-+28HZgKAuyCQnQwLSAwkHUqtMB/egHF5ACUABCB4Nev02/ZfjFPUTF/WloTaEbue34zLLUGxPXh+BJF8Xw26ow==
|
||||||
dependencies:
|
dependencies:
|
||||||
app-builder-lib "22.10.3"
|
app-builder-lib "22.10.4"
|
||||||
builder-util "22.10.3"
|
builder-util "22.10.4"
|
||||||
fs-extra "^9.0.1"
|
fs-extra "^9.0.1"
|
||||||
iconv-lite "^0.6.2"
|
iconv-lite "^0.6.2"
|
||||||
js-yaml "^3.14.1"
|
js-yaml "^3.14.1"
|
||||||
@@ -2265,18 +2334,18 @@ ejs@^3.1.5:
|
|||||||
dependencies:
|
dependencies:
|
||||||
jake "^10.6.1"
|
jake "^10.6.1"
|
||||||
|
|
||||||
electron-builder@22.10.3:
|
electron-builder@22.10.4:
|
||||||
version "22.10.3"
|
version "22.10.4"
|
||||||
resolved "https://registry.npmjs.org/electron-builder/-/electron-builder-22.10.3.tgz"
|
resolved "https://registry.yarnpkg.com/electron-builder/-/electron-builder-22.10.4.tgz#e1f400cf41ebb632fbf79aa86c5e0ab1ea1ed7e5"
|
||||||
integrity sha512-TNKmeYWrnATD/BBkpmNF03+wAA3+K8DZ6d/F1ipAKCbqeILp4agnr5nrngz+xpl7Y83lhelC1moU4utHNWYhzw==
|
integrity sha512-V+JtiizJd3kt24TT+0OHG7+oPAzjhhjmQVn9G6OC2WE7VBJxrDuD6lMVRgo6WlU8uvDCh7fTRUsdh0Tnu0GeQA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@types/yargs" "^15.0.11"
|
"@types/yargs" "^15.0.12"
|
||||||
app-builder-lib "22.10.3"
|
app-builder-lib "22.10.4"
|
||||||
bluebird-lst "^1.0.9"
|
bluebird-lst "^1.0.9"
|
||||||
builder-util "22.10.3"
|
builder-util "22.10.4"
|
||||||
builder-util-runtime "8.7.3"
|
builder-util-runtime "8.7.3"
|
||||||
chalk "^4.1.0"
|
chalk "^4.1.0"
|
||||||
dmg-builder "22.10.3"
|
dmg-builder "22.10.4"
|
||||||
fs-extra "^9.0.1"
|
fs-extra "^9.0.1"
|
||||||
is-ci "^2.0.0"
|
is-ci "^2.0.0"
|
||||||
lazy-val "^1.0.4"
|
lazy-val "^1.0.4"
|
||||||
@@ -2376,19 +2445,19 @@ electron-notarize@^1.0.0:
|
|||||||
debug "^4.1.1"
|
debug "^4.1.1"
|
||||||
fs-extra "^9.0.1"
|
fs-extra "^9.0.1"
|
||||||
|
|
||||||
electron-publish@22.10.3:
|
electron-publish@22.10.4:
|
||||||
version "22.10.3"
|
version "22.10.4"
|
||||||
resolved "https://registry.npmjs.org/electron-publish/-/electron-publish-22.10.3.tgz"
|
resolved "https://registry.yarnpkg.com/electron-publish/-/electron-publish-22.10.4.tgz#944b00aa6a7746c31ce900ffd8106d243326dca8"
|
||||||
integrity sha512-NGcgDp0xT92NPB5lGckroz2n5h8Ud53SShmwZoVtCp1W+VOSWn5CVPnXDquzf7pMcZRfo8qoMZrlvUeOlY4oIg==
|
integrity sha512-cjVM0+9DQoV4TWfH8lVWoelJ89O2i5yDARVp5GCMHrB43XEU0Nr5eKYysgsbOSnZk5W8z1vfGpFWHj+AeAEDYg==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@types/fs-extra" "^9.0.5"
|
"@types/fs-extra" "^9.0.5"
|
||||||
bluebird-lst "^1.0.9"
|
bluebird-lst "^1.0.9"
|
||||||
builder-util "22.10.3"
|
builder-util "22.10.4"
|
||||||
builder-util-runtime "8.7.3"
|
builder-util-runtime "8.7.3"
|
||||||
chalk "^4.1.0"
|
chalk "^4.1.0"
|
||||||
fs-extra "^9.0.1"
|
fs-extra "^9.0.1"
|
||||||
lazy-val "^1.0.4"
|
lazy-val "^1.0.4"
|
||||||
mime "^2.4.6"
|
mime "^2.4.7"
|
||||||
|
|
||||||
electron-rebuild@^2.3.4:
|
electron-rebuild@^2.3.4:
|
||||||
version "2.3.4"
|
version "2.3.4"
|
||||||
@@ -2413,13 +2482,13 @@ electron-to-chromium@^1.3.621:
|
|||||||
resolved "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.629.tgz"
|
resolved "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.629.tgz"
|
||||||
integrity sha512-iSPPJtPvHrMAvYOt+9cdbDmTasPqwnwz4lkP8Dn200gDNUBQOLQ96xUsWXBwXslAo5XxdoXAoQQ3RAy4uao9IQ==
|
integrity sha512-iSPPJtPvHrMAvYOt+9cdbDmTasPqwnwz4lkP8Dn200gDNUBQOLQ96xUsWXBwXslAo5XxdoXAoQQ3RAy4uao9IQ==
|
||||||
|
|
||||||
electron@^11.1.1:
|
electron@12.0.0-beta.16:
|
||||||
version "11.1.1"
|
version "12.0.0-beta.16"
|
||||||
resolved "https://registry.yarnpkg.com/electron/-/electron-11.1.1.tgz#188f036f8282798398dca9513e9bb3b10213e3aa"
|
resolved "https://registry.yarnpkg.com/electron/-/electron-12.0.0-beta.16.tgz#8142fe7af8ee85a181575063db689d6da4175899"
|
||||||
integrity sha512-tlbex3xosJgfileN6BAQRotevPRXB/wQIq48QeQ08tUJJrXwE72c8smsM/hbHx5eDgnbfJ2G3a60PmRjHU2NhA==
|
integrity sha512-8fsosa7PLnfheNqVK5G+NToZBh4audSVJIwff4vKorCkNK3XDMQCoHD9JKFeVRczYlb4YEY2mh7SsX4C8p9FMQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@electron/get" "^1.0.1"
|
"@electron/get" "^1.0.1"
|
||||||
"@types/node" "^12.0.12"
|
"@types/node" "^14.6.2"
|
||||||
extract-zip "^1.0.3"
|
extract-zip "^1.0.3"
|
||||||
|
|
||||||
emoji-regex@^7.0.1:
|
emoji-regex@^7.0.1:
|
||||||
@@ -2461,16 +2530,9 @@ end-of-stream@1.0.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
once "~1.3.0"
|
once "~1.3.0"
|
||||||
|
|
||||||
end-of-stream@^1.0.0:
|
end-of-stream@^1.0.0, end-of-stream@^1.1.0:
|
||||||
version "1.4.0"
|
|
||||||
resolved "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.0.tgz"
|
|
||||||
integrity sha1-epDYM+/abPpurA9JSduw+tOmMgY=
|
|
||||||
dependencies:
|
|
||||||
once "^1.4.0"
|
|
||||||
|
|
||||||
end-of-stream@^1.1.0:
|
|
||||||
version "1.4.4"
|
version "1.4.4"
|
||||||
resolved "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz"
|
resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0"
|
||||||
integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==
|
integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==
|
||||||
dependencies:
|
dependencies:
|
||||||
once "^1.4.0"
|
once "^1.4.0"
|
||||||
@@ -2591,13 +2653,13 @@ es6-iterator@~2.0.3:
|
|||||||
es6-symbol "^3.1.1"
|
es6-symbol "^3.1.1"
|
||||||
|
|
||||||
es6-promise@^4.0.3:
|
es6-promise@^4.0.3:
|
||||||
version "4.1.1"
|
version "4.2.8"
|
||||||
resolved "https://registry.npmjs.org/es6-promise/-/es6-promise-4.1.1.tgz"
|
resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a"
|
||||||
integrity sha512-OaU1hHjgJf+b0NzsxCg7NdIYERD6Hy/PEmFLTjw+b65scuisG3Kt4QoTvJ66BBkPZ581gr0kpoVzKnxniM8nng==
|
integrity sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==
|
||||||
|
|
||||||
es6-promisify@^5.0.0:
|
es6-promisify@^5.0.0:
|
||||||
version "5.0.0"
|
version "5.0.0"
|
||||||
resolved "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz"
|
resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-5.0.0.tgz#5109d62f3e56ea967c4b63505aef08291c8a5203"
|
||||||
integrity sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=
|
integrity sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=
|
||||||
dependencies:
|
dependencies:
|
||||||
es6-promise "^4.0.3"
|
es6-promise "^4.0.3"
|
||||||
@@ -3116,6 +3178,11 @@ from2@^2.1.0:
|
|||||||
inherits "^2.0.1"
|
inherits "^2.0.1"
|
||||||
readable-stream "^2.0.0"
|
readable-stream "^2.0.0"
|
||||||
|
|
||||||
|
fs-constants@^1.0.0:
|
||||||
|
version "1.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad"
|
||||||
|
integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==
|
||||||
|
|
||||||
fs-extra@^4.0.1:
|
fs-extra@^4.0.1:
|
||||||
version "4.0.3"
|
version "4.0.3"
|
||||||
resolved "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.3.tgz"
|
resolved "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.3.tgz"
|
||||||
@@ -3179,7 +3246,7 @@ fs-write-stream-atomic@^1.0.8, fs-write-stream-atomic@~1.0.10:
|
|||||||
|
|
||||||
fs.realpath@^1.0.0:
|
fs.realpath@^1.0.0:
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz"
|
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
|
||||||
integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8=
|
integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8=
|
||||||
|
|
||||||
fstream-ignore@^1.0.0:
|
fstream-ignore@^1.0.0:
|
||||||
@@ -3200,9 +3267,9 @@ fstream-npm@~1.2.1:
|
|||||||
inherits "2"
|
inherits "2"
|
||||||
|
|
||||||
fstream@^1.0.0, fstream@^1.0.2, fstream@~1.0.11:
|
fstream@^1.0.0, fstream@^1.0.2, fstream@~1.0.11:
|
||||||
version "1.0.11"
|
version "1.0.12"
|
||||||
resolved "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz"
|
resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.12.tgz#4e8ba8ee2d48be4f7d0de505455548eae5932045"
|
||||||
integrity sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=
|
integrity sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==
|
||||||
dependencies:
|
dependencies:
|
||||||
graceful-fs "^4.1.2"
|
graceful-fs "^4.1.2"
|
||||||
inherits "~2.0.0"
|
inherits "~2.0.0"
|
||||||
@@ -3464,6 +3531,11 @@ graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0,
|
|||||||
resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz"
|
resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz"
|
||||||
integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==
|
integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==
|
||||||
|
|
||||||
|
"graceful-readlink@>= 1.0.0":
|
||||||
|
version "1.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725"
|
||||||
|
integrity sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=
|
||||||
|
|
||||||
handlebars@^4.7.6:
|
handlebars@^4.7.6:
|
||||||
version "4.7.6"
|
version "4.7.6"
|
||||||
resolved "https://registry.npmjs.org/handlebars/-/handlebars-4.7.6.tgz"
|
resolved "https://registry.npmjs.org/handlebars/-/handlebars-4.7.6.tgz"
|
||||||
@@ -3659,12 +3731,12 @@ http-cache-semantics@^4.0.0:
|
|||||||
integrity sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==
|
integrity sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==
|
||||||
|
|
||||||
http-proxy-agent@^2.0.0:
|
http-proxy-agent@^2.0.0:
|
||||||
version "2.0.0"
|
version "2.1.0"
|
||||||
resolved "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-2.0.0.tgz"
|
resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz#e4821beef5b2142a2026bd73926fe537631c5405"
|
||||||
integrity sha1-RkgqLwUjpNYIJVFwn0acs+SoX/Q=
|
integrity sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==
|
||||||
dependencies:
|
dependencies:
|
||||||
agent-base "4"
|
agent-base "4"
|
||||||
debug "2"
|
debug "3.1.0"
|
||||||
|
|
||||||
http-signature@~1.1.0:
|
http-signature@~1.1.0:
|
||||||
version "1.1.1"
|
version "1.1.1"
|
||||||
@@ -3821,22 +3893,17 @@ indexes-of@^1.0.1:
|
|||||||
|
|
||||||
inflight@^1.0.4, inflight@~1.0.6:
|
inflight@^1.0.4, inflight@~1.0.6:
|
||||||
version "1.0.6"
|
version "1.0.6"
|
||||||
resolved "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz"
|
resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
|
||||||
integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=
|
integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=
|
||||||
dependencies:
|
dependencies:
|
||||||
once "^1.3.0"
|
once "^1.3.0"
|
||||||
wrappy "1"
|
wrappy "1"
|
||||||
|
|
||||||
inherits@2, inherits@^2.0.3, inherits@~2.0.1, inherits@~2.0.3:
|
inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3:
|
||||||
version "2.0.4"
|
version "2.0.4"
|
||||||
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
|
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
|
||||||
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
|
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
|
||||||
|
|
||||||
inherits@^2.0.1, inherits@~2.0.0:
|
|
||||||
version "2.0.3"
|
|
||||||
resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz"
|
|
||||||
integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=
|
|
||||||
|
|
||||||
ini@1.3.7:
|
ini@1.3.7:
|
||||||
version "1.3.7"
|
version "1.3.7"
|
||||||
resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.7.tgz#a09363e1911972ea16d7a8851005d84cf09a9a84"
|
resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.7.tgz#a09363e1911972ea16d7a8851005d84cf09a9a84"
|
||||||
@@ -4737,6 +4804,11 @@ lzma-native@^6.0.1:
|
|||||||
readable-stream "^2.3.5"
|
readable-stream "^2.3.5"
|
||||||
rimraf "^2.7.1"
|
rimraf "^2.7.1"
|
||||||
|
|
||||||
|
macos-release@^2.4.1:
|
||||||
|
version "2.4.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/macos-release/-/macos-release-2.4.1.tgz#64033d0ec6a5e6375155a74b1a1eba8e509820ac"
|
||||||
|
integrity sha512-H/QHeBIN1fIGJX517pvK8IEK53yQOW7YcEI55oYtgjDdoCQQz7eJS94qt5kNrscReEyuD/JcdFCm2XBEcGOITg==
|
||||||
|
|
||||||
make-dir@^1.0.0:
|
make-dir@^1.0.0:
|
||||||
version "1.3.0"
|
version "1.3.0"
|
||||||
resolved "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz"
|
resolved "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz"
|
||||||
@@ -4898,7 +4970,7 @@ mime-types@~2.1.7:
|
|||||||
dependencies:
|
dependencies:
|
||||||
mime-db "~1.27.0"
|
mime-db "~1.27.0"
|
||||||
|
|
||||||
mime@^2.4.4, mime@^2.4.6:
|
mime@^2.4.4, mime@^2.4.7:
|
||||||
version "2.4.7"
|
version "2.4.7"
|
||||||
resolved "https://registry.npmjs.org/mime/-/mime-2.4.7.tgz"
|
resolved "https://registry.npmjs.org/mime/-/mime-2.4.7.tgz"
|
||||||
integrity sha512-dhNd1uA2u397uQk3Nv5LM4lm93WYDUXFn3Fu291FJerns4jyTudqhIWe4W04YLy7Uk1tm1Ore04NpjRvQp/NPA==
|
integrity sha512-dhNd1uA2u397uQk3Nv5LM4lm93WYDUXFn3Fu291FJerns4jyTudqhIWe4W04YLy7Uk1tm1Ore04NpjRvQp/NPA==
|
||||||
@@ -4918,21 +4990,16 @@ mimic-response@^3.1.0:
|
|||||||
resolved "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz"
|
resolved "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz"
|
||||||
integrity sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==
|
integrity sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==
|
||||||
|
|
||||||
minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4, minimatch@~3.0.2:
|
minimatch@3.0.4, minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4, minimatch@~3.0.2:
|
||||||
version "3.0.4"
|
version "3.0.4"
|
||||||
resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz"
|
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
|
||||||
integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==
|
integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==
|
||||||
dependencies:
|
dependencies:
|
||||||
brace-expansion "^1.1.7"
|
brace-expansion "^1.1.7"
|
||||||
|
|
||||||
minimist@0.0.8:
|
|
||||||
version "0.0.8"
|
|
||||||
resolved "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz"
|
|
||||||
integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=
|
|
||||||
|
|
||||||
minimist@^1.1.0, minimist@^1.1.3, minimist@^1.2.0, minimist@^1.2.5:
|
minimist@^1.1.0, minimist@^1.1.3, minimist@^1.2.0, minimist@^1.2.5:
|
||||||
version "1.2.5"
|
version "1.2.5"
|
||||||
resolved "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz"
|
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602"
|
||||||
integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==
|
integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==
|
||||||
|
|
||||||
minipass@^2.6.0, minipass@^2.8.6, minipass@^2.9.0:
|
minipass@^2.6.0, minipass@^2.8.6, minipass@^2.9.0:
|
||||||
@@ -4989,14 +5056,7 @@ mixin-deep@^1.2.0:
|
|||||||
for-in "^1.0.2"
|
for-in "^1.0.2"
|
||||||
is-extendable "^1.0.1"
|
is-extendable "^1.0.1"
|
||||||
|
|
||||||
"mkdirp@>=0.5 0", mkdirp@~0.5.0, mkdirp@~0.5.1:
|
"mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@^0.5.4, mkdirp@^0.5.5, mkdirp@~0.5.0, mkdirp@~0.5.1:
|
||||||
version "0.5.1"
|
|
||||||
resolved "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz"
|
|
||||||
integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=
|
|
||||||
dependencies:
|
|
||||||
minimist "0.0.8"
|
|
||||||
|
|
||||||
mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@^0.5.4, mkdirp@^0.5.5:
|
|
||||||
version "0.5.5"
|
version "0.5.5"
|
||||||
resolved "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz"
|
resolved "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz"
|
||||||
integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==
|
integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==
|
||||||
@@ -5381,9 +5441,9 @@ npm-run-path@^4.0.0:
|
|||||||
path-key "^3.0.0"
|
path-key "^3.0.0"
|
||||||
|
|
||||||
npm-user-validate@~1.0.0:
|
npm-user-validate@~1.0.0:
|
||||||
version "1.0.0"
|
version "1.0.1"
|
||||||
resolved "https://registry.npmjs.org/npm-user-validate/-/npm-user-validate-1.0.0.tgz"
|
resolved "https://registry.yarnpkg.com/npm-user-validate/-/npm-user-validate-1.0.1.tgz#31428fc5475fe8416023f178c0ab47935ad8c561"
|
||||||
integrity sha1-jOyg9c6gTU6TUZ73LQVXp1Ei6VE=
|
integrity sha512-uQwcd/tY+h1jnEaze6cdX/LrhWhoBxfSknxentoqmIuStxUExxjWd3ULMLFPiFUrZKbOVMowH6Jq2FRWfmhcEw==
|
||||||
|
|
||||||
npm@5.1.0:
|
npm@5.1.0:
|
||||||
version "5.1.0"
|
version "5.1.0"
|
||||||
@@ -5588,7 +5648,7 @@ object.values@^1.1.1:
|
|||||||
|
|
||||||
once@^1.3.0, once@^1.3.1, once@^1.3.3, once@^1.4.0, once@~1.4.0:
|
once@^1.3.0, once@^1.3.1, once@^1.3.3, once@^1.4.0, once@~1.4.0:
|
||||||
version "1.4.0"
|
version "1.4.0"
|
||||||
resolved "https://registry.npmjs.org/once/-/once-1.4.0.tgz"
|
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
|
||||||
integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E=
|
integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E=
|
||||||
dependencies:
|
dependencies:
|
||||||
wrappy "1"
|
wrappy "1"
|
||||||
@@ -5865,7 +5925,7 @@ path-exists@^4.0.0:
|
|||||||
|
|
||||||
path-is-absolute@^1.0.0:
|
path-is-absolute@^1.0.0:
|
||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz"
|
resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
|
||||||
integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18=
|
integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18=
|
||||||
|
|
||||||
path-is-inside@^1.0.1, path-is-inside@~1.0.2:
|
path-is-inside@^1.0.1, path-is-inside@~1.0.2:
|
||||||
@@ -6315,9 +6375,9 @@ pug@^2.0.0-rc.2, pug@^2.0.4:
|
|||||||
pug-strip-comments "^1.0.4"
|
pug-strip-comments "^1.0.4"
|
||||||
|
|
||||||
pump@^1.0.0:
|
pump@^1.0.0:
|
||||||
version "1.0.2"
|
version "1.0.3"
|
||||||
resolved "https://registry.npmjs.org/pump/-/pump-1.0.2.tgz"
|
resolved "https://registry.yarnpkg.com/pump/-/pump-1.0.3.tgz#5dfe8311c33bbf6fc18261f9f34702c47c08a954"
|
||||||
integrity sha1-Oz7mUS+U8OV1U4wXmV+fFpkKXVE=
|
integrity sha512-8k0JupWme55+9tCVE+FS5ULT3K6AbgqrGa58lTT49RpyfwwcGedHqaC5LlQNdEAumn/wFsu6aPwkuPMioy8kqw==
|
||||||
dependencies:
|
dependencies:
|
||||||
end-of-stream "^1.1.0"
|
end-of-stream "^1.1.0"
|
||||||
once "^1.3.1"
|
once "^1.3.1"
|
||||||
@@ -6491,7 +6551,7 @@ read@1, read@~1.0.1, read@~1.0.7:
|
|||||||
dependencies:
|
dependencies:
|
||||||
mute-stream "~0.0.4"
|
mute-stream "~0.0.4"
|
||||||
|
|
||||||
"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.4, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.5, readable-stream@~2.3.2:
|
"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.4, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.0, readable-stream@^2.3.5, readable-stream@~2.3.2:
|
||||||
version "2.3.7"
|
version "2.3.7"
|
||||||
resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz"
|
resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz"
|
||||||
integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==
|
integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==
|
||||||
@@ -6778,14 +6838,7 @@ right-align@^0.1.1:
|
|||||||
dependencies:
|
dependencies:
|
||||||
align-text "^0.1.1"
|
align-text "^0.1.1"
|
||||||
|
|
||||||
rimraf@2, rimraf@^2.5.2, rimraf@^2.5.4, rimraf@~2.6.1:
|
rimraf@2, rimraf@^2.5.2, rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.2, rimraf@^2.6.3, rimraf@^2.7.1:
|
||||||
version "2.6.1"
|
|
||||||
resolved "https://registry.npmjs.org/rimraf/-/rimraf-2.6.1.tgz"
|
|
||||||
integrity sha1-wjOOxkPfeht/5cVPqG9XQopV8z0=
|
|
||||||
dependencies:
|
|
||||||
glob "^7.0.5"
|
|
||||||
|
|
||||||
rimraf@^2.6.1, rimraf@^2.6.2, rimraf@^2.6.3, rimraf@^2.7.1:
|
|
||||||
version "2.7.1"
|
version "2.7.1"
|
||||||
resolved "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz"
|
resolved "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz"
|
||||||
integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==
|
integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==
|
||||||
@@ -6799,6 +6852,13 @@ rimraf@^3.0.0, rimraf@^3.0.2:
|
|||||||
dependencies:
|
dependencies:
|
||||||
glob "^7.1.3"
|
glob "^7.1.3"
|
||||||
|
|
||||||
|
rimraf@~2.6.1:
|
||||||
|
version "2.6.1"
|
||||||
|
resolved "https://registry.npmjs.org/rimraf/-/rimraf-2.6.1.tgz"
|
||||||
|
integrity sha1-wjOOxkPfeht/5cVPqG9XQopV8z0=
|
||||||
|
dependencies:
|
||||||
|
glob "^7.0.5"
|
||||||
|
|
||||||
roarr@^2.15.3:
|
roarr@^2.15.3:
|
||||||
version "2.15.4"
|
version "2.15.4"
|
||||||
resolved "https://registry.npmjs.org/roarr/-/roarr-2.15.4.tgz"
|
resolved "https://registry.npmjs.org/roarr/-/roarr-2.15.4.tgz"
|
||||||
@@ -6878,7 +6938,7 @@ sax@^1.2.4:
|
|||||||
resolved "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz"
|
resolved "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz"
|
||||||
integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==
|
integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==
|
||||||
|
|
||||||
schema-utils@^2.5.0, schema-utils@^2.6.0, schema-utils@^2.6.5, schema-utils@^2.7.0:
|
schema-utils@^2.5.0, schema-utils@^2.6.0, schema-utils@^2.6.5:
|
||||||
version "2.7.1"
|
version "2.7.1"
|
||||||
resolved "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz"
|
resolved "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz"
|
||||||
integrity sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==
|
integrity sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==
|
||||||
@@ -7384,9 +7444,9 @@ string_decoder@~1.1.1:
|
|||||||
safe-buffer "~5.1.0"
|
safe-buffer "~5.1.0"
|
||||||
|
|
||||||
stringstream@~0.0.4:
|
stringstream@~0.0.4:
|
||||||
version "0.0.5"
|
version "0.0.6"
|
||||||
resolved "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz"
|
resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.6.tgz#7880225b0d4ad10e30927d167a1d6f2fd3b33a72"
|
||||||
integrity sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=
|
integrity sha512-87GEBAkegbBcweToUrdzf3eLhWNg06FJTebl4BVJz/JgWy8CvEr9dRtX5qWphiynMSQlxxi+QqN0z5T32SLlhA==
|
||||||
|
|
||||||
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"
|
||||||
@@ -7455,13 +7515,13 @@ strip-json-comments@^3.1.0, strip-json-comments@^3.1.1:
|
|||||||
resolved "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz"
|
resolved "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz"
|
||||||
integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==
|
integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==
|
||||||
|
|
||||||
style-loader@^1.3.0:
|
style-loader@^2.0.0:
|
||||||
version "1.3.0"
|
version "2.0.0"
|
||||||
resolved "https://registry.npmjs.org/style-loader/-/style-loader-1.3.0.tgz"
|
resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-2.0.0.tgz#9669602fd4690740eaaec137799a03addbbc393c"
|
||||||
integrity sha512-V7TCORko8rs9rIqkSrlMfkqA63DfoGBBJmK1kKGCcSi+BWb4cqz0SRsnp4l6rU5iwOEd0/2ePv68SV22VXon4Q==
|
integrity sha512-Z0gYUJmzZ6ZdRUqpg1r8GsaFKypE+3xAzuFeMuoHgjc9KZv3wMyCRjQIWEbhoFSq7+7yoHXySDJyyWQaPajeiQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
loader-utils "^2.0.0"
|
loader-utils "^2.0.0"
|
||||||
schema-utils "^2.7.0"
|
schema-utils "^3.0.0"
|
||||||
|
|
||||||
sumchecker@^2.0.2:
|
sumchecker@^2.0.2:
|
||||||
version "2.0.2"
|
version "2.0.2"
|
||||||
@@ -7543,9 +7603,9 @@ tapable@^2.0.0, tapable@^2.1.1:
|
|||||||
integrity sha512-FBk4IesMV1rBxX2tfiK8RAmogtWn53puLOQlvO8XuwlgxcYbP4mVPS9Ph4aeamSyyVjOl24aYWAuc8U5kCVwMw==
|
integrity sha512-FBk4IesMV1rBxX2tfiK8RAmogtWn53puLOQlvO8XuwlgxcYbP4mVPS9Ph4aeamSyyVjOl24aYWAuc8U5kCVwMw==
|
||||||
|
|
||||||
tar-fs@^1.15.3:
|
tar-fs@^1.15.3:
|
||||||
version "1.15.3"
|
version "1.16.3"
|
||||||
resolved "https://registry.npmjs.org/tar-fs/-/tar-fs-1.15.3.tgz"
|
resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-1.16.3.tgz#966a628841da2c4010406a82167cbd5e0c72d509"
|
||||||
integrity sha1-7M+TXpQUk9gVECjmNuUc5MPKfyA=
|
integrity sha512-NvCeXpYx7OsmOh8zIOP/ebG55zZmxLE0etfWRbWok+q2Qo8x/vOR/IJT1taADXPe+jsiu9axDb3X4B+iIgNlKw==
|
||||||
dependencies:
|
dependencies:
|
||||||
chownr "^1.0.1"
|
chownr "^1.0.1"
|
||||||
mkdirp "^0.5.1"
|
mkdirp "^0.5.1"
|
||||||
@@ -7553,13 +7613,16 @@ tar-fs@^1.15.3:
|
|||||||
tar-stream "^1.1.2"
|
tar-stream "^1.1.2"
|
||||||
|
|
||||||
tar-stream@^1.1.2, tar-stream@^1.5.4:
|
tar-stream@^1.1.2, tar-stream@^1.5.4:
|
||||||
version "1.5.4"
|
version "1.6.2"
|
||||||
resolved "https://registry.npmjs.org/tar-stream/-/tar-stream-1.5.4.tgz"
|
resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.6.2.tgz#8ea55dab37972253d9a9af90fdcd559ae435c555"
|
||||||
integrity sha1-NlSc8E7RrumyowwBQyUiONr5QBY=
|
integrity sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==
|
||||||
dependencies:
|
dependencies:
|
||||||
bl "^1.0.0"
|
bl "^1.0.0"
|
||||||
|
buffer-alloc "^1.2.0"
|
||||||
end-of-stream "^1.0.0"
|
end-of-stream "^1.0.0"
|
||||||
readable-stream "^2.0.0"
|
fs-constants "^1.0.0"
|
||||||
|
readable-stream "^2.3.0"
|
||||||
|
to-buffer "^1.1.1"
|
||||||
xtend "^4.0.0"
|
xtend "^4.0.0"
|
||||||
|
|
||||||
tar@^2.0.0, tar@~2.2.1:
|
tar@^2.0.0, tar@~2.2.1:
|
||||||
@@ -7708,6 +7771,11 @@ tmp@^0.2.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
rimraf "^3.0.0"
|
rimraf "^3.0.0"
|
||||||
|
|
||||||
|
to-buffer@^1.1.1:
|
||||||
|
version "1.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/to-buffer/-/to-buffer-1.1.1.tgz#493bd48f62d7c43fcded313a03dcadb2e1213a80"
|
||||||
|
integrity sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==
|
||||||
|
|
||||||
to-fast-properties@^1.0.3:
|
to-fast-properties@^1.0.3:
|
||||||
version "1.0.3"
|
version "1.0.3"
|
||||||
resolved "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz"
|
resolved "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz"
|
||||||
@@ -8414,7 +8482,7 @@ wrap-ansi@^7.0.0:
|
|||||||
|
|
||||||
wrappy@1, wrappy@~1.0.2:
|
wrappy@1, wrappy@~1.0.2:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
resolved "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz"
|
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
|
||||||
integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=
|
integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=
|
||||||
|
|
||||||
write-file-atomic@^2.0.0, write-file-atomic@^2.3.0:
|
write-file-atomic@^2.0.0, write-file-atomic@^2.3.0:
|
||||||
@@ -8470,11 +8538,16 @@ xmldom@0.1.x:
|
|||||||
resolved "https://registry.npmjs.org/xmldom/-/xmldom-0.1.31.tgz"
|
resolved "https://registry.npmjs.org/xmldom/-/xmldom-0.1.31.tgz"
|
||||||
integrity sha512-yS2uJflVQs6n+CyjHoaBmVSqIDevTAWrzMmjG1Gc7h1qQ7uVozNhEPJAwZXWyGQ/Gafo3fCwrcaokezLPupVyQ==
|
integrity sha512-yS2uJflVQs6n+CyjHoaBmVSqIDevTAWrzMmjG1Gc7h1qQ7uVozNhEPJAwZXWyGQ/Gafo3fCwrcaokezLPupVyQ==
|
||||||
|
|
||||||
"xtend@>=4.0.0 <4.1.0-0", xtend@^4.0.0, xtend@~4.0.1:
|
"xtend@>=4.0.0 <4.1.0-0", xtend@~4.0.1:
|
||||||
version "4.0.1"
|
version "4.0.1"
|
||||||
resolved "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz"
|
resolved "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz"
|
||||||
integrity sha1-pcbVMr5lbiPbgg77lDofBJmNY68=
|
integrity sha1-pcbVMr5lbiPbgg77lDofBJmNY68=
|
||||||
|
|
||||||
|
xtend@^4.0.0:
|
||||||
|
version "4.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"
|
||||||
|
integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==
|
||||||
|
|
||||||
xtend@~2.1.1:
|
xtend@~2.1.1:
|
||||||
version "2.1.2"
|
version "2.1.2"
|
||||||
resolved "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz"
|
resolved "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz"
|
||||||
|
Reference in New Issue
Block a user