Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
gzupanda
code-server
提交
8cc11d16
C
code-server
项目概览
gzupanda
/
code-server
与 Fork 源项目一致
从无法访问的项目Fork
通知
2
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
C
code-server
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
未验证
提交
8cc11d16
编写于
2月 04, 2020
作者:
A
Asher
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Improve routing
上级
dbc5c065
变更
26
显示空白变更内容
内联
并排
Showing
26 changed file
with
288 addition
and
266 deletion
+288
-266
package.json
package.json
+2
-2
scripts/build.ts
scripts/build.ts
+18
-0
src/browser/app.css
src/browser/app.css
+5
-0
src/browser/app.tsx
src/browser/app.tsx
+23
-18
src/browser/components/animate.tsx
src/browser/components/animate.tsx
+4
-0
src/browser/components/error.tsx
src/browser/components/error.tsx
+2
-1
src/browser/components/list.css
src/browser/components/list.css
+4
-1
src/browser/components/list.tsx
src/browser/components/list.tsx
+37
-5
src/browser/components/modal.css
src/browser/components/modal.css
+15
-10
src/browser/components/modal.tsx
src/browser/components/modal.tsx
+50
-46
src/browser/index.tsx
src/browser/index.tsx
+3
-7
src/browser/pages/browse.tsx
src/browser/pages/browse.tsx
+2
-3
src/browser/pages/home.tsx
src/browser/pages/home.tsx
+8
-10
src/browser/pages/login.css
src/browser/pages/login.css
+9
-5
src/browser/pages/login.tsx
src/browser/pages/login.tsx
+7
-18
src/browser/pages/missing.css
src/browser/pages/missing.css
+8
-0
src/browser/pages/missing.tsx
src/browser/pages/missing.tsx
+9
-0
src/common/api.ts
src/common/api.ts
+1
-0
src/common/util.ts
src/common/util.ts
+13
-0
src/node/api/server.ts
src/node/api/server.ts
+1
-0
src/node/app/server.tsx
src/node/app/server.tsx
+29
-13
src/node/entry.ts
src/node/entry.ts
+11
-4
src/node/http.ts
src/node/http.ts
+6
-3
src/node/util.ts
src/node/util.ts
+0
-7
test/util.test.ts
test/util.test.ts
+7
-1
yarn.lock
yarn.lock
+14
-112
未找到文件。
package.json
浏览文件 @
8cc11d16
...
@@ -22,13 +22,13 @@
...
@@ -22,13 +22,13 @@
"devDependencies"
:
{
"devDependencies"
:
{
"
@coder/nbin
"
:
"
^1.2.7
"
,
"
@coder/nbin
"
:
"
^1.2.7
"
,
"
@types/fs-extra
"
:
"
^8.0.1
"
,
"
@types/fs-extra
"
:
"
^8.0.1
"
,
"
@types/hookrouter
"
:
"
^2.2.1
"
,
"
@types/mocha
"
:
"
^5.2.7
"
,
"
@types/mocha
"
:
"
^5.2.7
"
,
"
@types/node
"
:
"
^12.12.7
"
,
"
@types/node
"
:
"
^12.12.7
"
,
"
@types/parcel-bundler
"
:
"
^1.12.1
"
,
"
@types/parcel-bundler
"
:
"
^1.12.1
"
,
"
@types/pem
"
:
"
^1.9.5
"
,
"
@types/pem
"
:
"
^1.9.5
"
,
"
@types/react
"
:
"
^16.9.18
"
,
"
@types/react
"
:
"
^16.9.18
"
,
"
@types/react-dom
"
:
"
^16.9.5
"
,
"
@types/react-dom
"
:
"
^16.9.5
"
,
"
@types/react-router-dom
"
:
"
^5.1.3
"
,
"
@types/safe-compare
"
:
"
^1.1.0
"
,
"
@types/safe-compare
"
:
"
^1.1.0
"
,
"
@types/tar-fs
"
:
"
^1.16.1
"
,
"
@types/tar-fs
"
:
"
^1.16.1
"
,
"
@types/tar-stream
"
:
"
^1.6.1
"
,
"
@types/tar-stream
"
:
"
^1.6.1
"
,
...
@@ -58,11 +58,11 @@
...
@@ -58,11 +58,11 @@
"dependencies"
:
{
"dependencies"
:
{
"
@coder/logger
"
:
"
1.1.11
"
,
"
@coder/logger
"
:
"
1.1.11
"
,
"
fs-extra
"
:
"
^8.1.0
"
,
"
fs-extra
"
:
"
^8.1.0
"
,
"
hookrouter
"
:
"
^1.2.3
"
,
"
httpolyglot
"
:
"
^0.1.2
"
,
"
httpolyglot
"
:
"
^0.1.2
"
,
"
pem
"
:
"
^1.14.2
"
,
"
pem
"
:
"
^1.14.2
"
,
"
react
"
:
"
^16.12.0
"
,
"
react
"
:
"
^16.12.0
"
,
"
react-dom
"
:
"
^16.12.0
"
,
"
react-dom
"
:
"
^16.12.0
"
,
"
react-router-dom
"
:
"
^5.1.2
"
,
"
safe-compare
"
:
"
^1.1.4
"
,
"
safe-compare
"
:
"
^1.1.4
"
,
"
tar-fs
"
:
"
^2.0.0
"
,
"
tar-fs
"
:
"
^2.0.0
"
,
"
tar-stream
"
:
"
^2.1.0
"
,
"
tar-stream
"
:
"
^2.1.0
"
,
...
...
scripts/build.ts
浏览文件 @
8cc11d16
...
@@ -173,6 +173,21 @@ class Builder {
...
@@ -173,6 +173,21 @@ class Builder {
})
})
await
this
.
copyDependencies
(
"
code-server
"
,
this
.
rootPath
,
this
.
buildPath
)
await
this
.
copyDependencies
(
"
code-server
"
,
this
.
rootPath
,
this
.
buildPath
)
await
this
.
task
(
"
writing final code-server package.json
"
,
async
()
=>
{
const
json
=
JSON
.
parse
(
await
fs
.
readFile
(
path
.
join
(
this
.
buildPath
,
"
package.json
"
),
"
utf8
"
))
return
fs
.
writeFile
(
path
.
join
(
this
.
buildPath
,
"
package.json
"
),
JSON
.
stringify
(
{
...
json
,
commit
,
},
null
,
2
)
)
})
}
}
private
async
buildVscode
(
commit
:
string
):
Promise
<
void
>
{
private
async
buildVscode
(
commit
:
string
):
Promise
<
void
>
{
...
@@ -369,6 +384,9 @@ class Builder {
...
@@ -369,6 +384,9 @@ class Builder {
bundler
.
on
(
"
buildEnd
"
,
()
=>
{
bundler
.
on
(
"
buildEnd
"
,
()
=>
{
console
.
log
(
"
[parcel] bundled
"
)
console
.
log
(
"
[parcel] bundled
"
)
})
})
bundler
.
on
(
"
buildError
"
,
(
error
)
=>
{
console
.
error
(
"
[parcel]
"
,
error
)
})
vscode
.
stderr
.
on
(
"
data
"
,
(
d
)
=>
process
.
stderr
.
write
(
d
))
vscode
.
stderr
.
on
(
"
data
"
,
(
d
)
=>
process
.
stderr
.
write
(
d
))
tsc
.
stderr
.
on
(
"
data
"
,
(
d
)
=>
process
.
stderr
.
write
(
d
))
tsc
.
stderr
.
on
(
"
data
"
,
(
d
)
=>
process
.
stderr
.
write
(
d
))
...
...
src/browser/app.css
浏览文件 @
8cc11d16
...
@@ -12,7 +12,12 @@ iframe {
...
@@ -12,7 +12,12 @@ iframe {
body
{
body
{
background
:
#272727
;
background
:
#272727
;
color
:
#f4f4f4
;
margin
:
0
;
margin
:
0
;
font-family
:
'IBM Plex Sans'
,
sans-serif
;
font-family
:
'IBM Plex Sans'
,
sans-serif
;
overflow
:
hidden
;
overflow
:
hidden
;
}
}
button
{
font-family
:
inherit
;
}
src/browser/app.tsx
浏览文件 @
8cc11d16
import
{
getBasepath
,
navigate
}
from
"
hookrouter
"
import
*
as
React
from
"
react
"
import
*
as
React
from
"
react
"
import
{
Application
}
from
"
../common/api
"
import
{
Application
,
isExecutableApplication
}
from
"
../common/api
"
import
{
Route
,
Switch
}
from
"
react-router-dom
"
import
{
HttpError
}
from
"
../common/http
"
import
{
HttpError
}
from
"
../common/http
"
import
{
normalize
,
Options
}
from
"
../common/util
"
import
{
Modal
}
from
"
./components/modal
"
import
{
Modal
}
from
"
./components/modal
"
import
{
getOptions
}
from
"
../common/util
"
const
App
:
React
.
FunctionComponent
=
()
=>
{
export
interface
AppProps
{
const
[
authed
,
setAuthed
]
=
React
.
useState
<
boolean
>
(
false
)
options
:
Options
const
[
app
,
setApp
]
=
React
.
useState
<
Application
>
()
}
const
App
:
React
.
FunctionComponent
<
AppProps
>
=
(
props
)
=>
{
const
[
authed
,
setAuthed
]
=
React
.
useState
<
boolean
>
(
!!
props
.
options
.
authed
)
const
[
app
,
setApp
]
=
React
.
useState
<
Application
|
undefined
>
(
props
.
options
.
app
)
const
[
error
,
setError
]
=
React
.
useState
<
HttpError
|
Error
|
string
>
()
const
[
error
,
setError
]
=
React
.
useState
<
HttpError
|
Error
|
string
>
()
React
.
useEffect
(()
=>
{
React
.
useEffect
(()
=>
{
getOptions
()
if
(
app
&&
!
isExecutableApplication
(
app
))
{
},
[])
navigate
(
normalize
(
`
${
getBasepath
()}
/
${
app
.
path
}
/`
,
true
))
}
},
[
app
])
if
(
typeof
window
!==
"
undefined
"
)
{
if
(
typeof
window
!==
"
undefined
"
)
{
// eslint-disable-next-line @typescript-eslint/no-explicit-any
// eslint-disable-next-line @typescript-eslint/no-explicit-any
;(
window
as
any
).
setAuthed
=
setAuthed
;(
window
as
any
).
setAuthed
=
(
a
:
boolean
):
void
=>
{
if
(
authed
!==
a
)
{
setAuthed
(
a
)
}
}
}
}
return
(
return
(
<>
<>
<
Switch
>
<
Route
path
=
"/vscode"
render
=
{
():
React
.
ReactElement
=>
<
iframe
id
=
"iframe"
src
=
"/vscode-embed"
></
iframe
>
}
/>
<
Route
path
=
"/"
render
=
{
():
React
.
ReactElement
=>
(
<
Modal
app
=
{
app
}
setApp
=
{
setApp
}
authed
=
{
authed
}
error
=
{
error
}
setError
=
{
setError
}
/>
<
Modal
app
=
{
app
}
setApp
=
{
setApp
}
authed
=
{
authed
}
error
=
{
error
}
setError
=
{
setError
}
/>
)
}
{
authed
&&
app
&&
app
.
embedPath
?
(
/
>
<
iframe
id
=
"iframe"
src
=
{
normalize
(
`
${
getBasepath
()}
/
${
app
.
embedPath
}
/`
,
true
)
}
></
iframe
>
</
Switch
>
)
:
null
}
</>
</>
)
)
}
}
...
...
src/browser/components/animate.tsx
浏览文件 @
8cc11d16
...
@@ -5,6 +5,10 @@ export interface DelayProps {
...
@@ -5,6 +5,10 @@ export interface DelayProps {
readonly
delay
:
number
readonly
delay
:
number
}
}
/**
* Animate a component before unmounting (by delaying unmounting) or after
* mounting.
*/
export
const
Animate
:
React
.
FunctionComponent
<
DelayProps
>
=
(
props
)
=>
{
export
const
Animate
:
React
.
FunctionComponent
<
DelayProps
>
=
(
props
)
=>
{
const
[
timer
,
setTimer
]
=
React
.
useState
<
NodeJS
.
Timeout
>
()
const
[
timer
,
setTimer
]
=
React
.
useState
<
NodeJS
.
Timeout
>
()
const
[
mount
,
setMount
]
=
React
.
useState
<
boolean
>
(
false
)
const
[
mount
,
setMount
]
=
React
.
useState
<
boolean
>
(
false
)
...
...
src/browser/components/error.tsx
浏览文件 @
8cc11d16
...
@@ -4,6 +4,7 @@ import { HttpError } from "../../common/http"
...
@@ -4,6 +4,7 @@ import { HttpError } from "../../common/http"
export
interface
ErrorProps
{
export
interface
ErrorProps
{
error
:
HttpError
|
Error
|
string
error
:
HttpError
|
Error
|
string
onClose
?:
()
=>
void
onClose
?:
()
=>
void
onCloseText
?:
string
}
}
/**
/**
...
@@ -15,7 +16,7 @@ export const RequestError: React.FunctionComponent<ErrorProps> = (props) => {
...
@@ -15,7 +16,7 @@ export const RequestError: React.FunctionComponent<ErrorProps> = (props) => {
<
div
className
=
"error"
>
{
typeof
props
.
error
===
"
string
"
?
props
.
error
:
props
.
error
.
message
}
</
div
>
<
div
className
=
"error"
>
{
typeof
props
.
error
===
"
string
"
?
props
.
error
:
props
.
error
.
message
}
</
div
>
{
props
.
onClose
?
(
{
props
.
onClose
?
(
<
button
className
=
"close"
onClick
=
{
props
.
onClose
}
>
<
button
className
=
"close"
onClick
=
{
props
.
onClose
}
>
Go Back
{
props
.
onCloseText
||
"
Close
"
}
</
button
>
</
button
>
)
:
(
)
:
(
undefined
undefined
...
...
src/browser/components/list.css
浏览文件 @
8cc11d16
...
@@ -20,7 +20,6 @@
...
@@ -20,7 +20,6 @@
.app-row
{
.app-row
{
color
:
#b6b6b6
;
color
:
#b6b6b6
;
cursor
:
pointer
;
display
:
flex
;
display
:
flex
;
font-size
:
1em
;
font-size
:
1em
;
line-height
:
1em
;
line-height
:
1em
;
...
@@ -106,3 +105,7 @@
...
@@ -106,3 +105,7 @@
.app-list
>
.loader
{
.app-list
>
.loader
{
color
:
#b6b6b6
;
color
:
#b6b6b6
;
}
}
.app-list
>
.app-row
{
cursor
:
pointer
;
}
src/browser/components/list.tsx
浏览文件 @
8cc11d16
...
@@ -4,6 +4,9 @@ import { HttpError } from "../../common/http"
...
@@ -4,6 +4,9 @@ import { HttpError } from "../../common/http"
import
{
getSession
,
killSession
}
from
"
../api
"
import
{
getSession
,
killSession
}
from
"
../api
"
import
{
RequestError
}
from
"
../components/error
"
import
{
RequestError
}
from
"
../components/error
"
/**
* An application's details (name and icon).
*/
export
const
AppDetails
:
React
.
FunctionComponent
<
Application
>
=
(
props
)
=>
{
export
const
AppDetails
:
React
.
FunctionComponent
<
Application
>
=
(
props
)
=>
{
return
(
return
(
<>
<>
...
@@ -23,6 +26,9 @@ export interface AppRowProps {
...
@@ -23,6 +26,9 @@ export interface AppRowProps {
open
(
app
:
Application
):
void
open
(
app
:
Application
):
void
}
}
/**
* A single application row. Can be killed if it's a running application.
*/
export
const
AppRow
:
React
.
FunctionComponent
<
AppRowProps
>
=
(
props
)
=>
{
export
const
AppRow
:
React
.
FunctionComponent
<
AppRowProps
>
=
(
props
)
=>
{
const
[
killing
,
setKilling
]
=
React
.
useState
<
boolean
>
(
false
)
const
[
killing
,
setKilling
]
=
React
.
useState
<
boolean
>
(
false
)
const
[
error
,
setError
]
=
React
.
useState
<
HttpError
>
()
const
[
error
,
setError
]
=
React
.
useState
<
HttpError
>
()
...
@@ -65,6 +71,11 @@ export interface AppListProps {
...
@@ -65,6 +71,11 @@ export interface AppListProps {
onKilled
(
app
:
Application
):
void
onKilled
(
app
:
Application
):
void
}
}
/**
* A list of applications. If undefined, show loading text. If empty, show a
* message saying no items are found. Applications can be clicked and killed
* (when applicable).
*/
export
const
AppList
:
React
.
FunctionComponent
<
AppListProps
>
=
(
props
)
=>
{
export
const
AppList
:
React
.
FunctionComponent
<
AppListProps
>
=
(
props
)
=>
{
return
(
return
(
<
div
className
=
"app-list"
>
<
div
className
=
"app-list"
>
...
@@ -92,11 +103,12 @@ export interface AppLoaderProps {
...
@@ -92,11 +103,12 @@ export interface AppLoaderProps {
}
}
/**
/**
* Display provided applications or sessions and allow opening them.
* Application sections/groups. Handles loading of the application
* sections, errors, opening applications, and killing applications.
*/
*/
export
const
AppLoader
:
React
.
FunctionComponent
<
AppLoaderProps
>
=
(
props
)
=>
{
export
const
AppLoader
:
React
.
FunctionComponent
<
AppLoaderProps
>
=
(
props
)
=>
{
const
[
apps
,
setApps
]
=
React
.
useState
<
ReadonlyArray
<
ApplicationSection
>>
()
const
[
apps
,
setApps
]
=
React
.
useState
<
ReadonlyArray
<
ApplicationSection
>>
()
const
[
error
,
setError
]
=
React
.
useState
<
HttpError
>
()
const
[
error
,
setError
]
=
React
.
useState
<
HttpError
|
Error
>
()
const
refresh
=
():
void
=>
{
const
refresh
=
():
void
=>
{
props
props
...
@@ -105,33 +117,51 @@ export const AppLoader: React.FunctionComponent<AppLoaderProps> = (props) => {
...
@@ -105,33 +117,51 @@ export const AppLoader: React.FunctionComponent<AppLoaderProps> = (props) => {
.
catch
((
e
)
=>
setError
(
e
.
message
))
.
catch
((
e
)
=>
setError
(
e
.
message
))
}
}
// Every time the component loads go ahead and refresh the list.
React
.
useEffect
(()
=>
{
React
.
useEffect
(()
=>
{
refresh
()
refresh
()
},
[
props
])
},
[
props
])
/**
* Open an application if not already open. For executable applications create
* a session first.
*/
function
open
(
app
:
Application
):
void
{
function
open
(
app
:
Application
):
void
{
if
(
props
.
app
&&
props
.
app
.
name
===
app
.
name
)
{
return
setError
(
new
Error
(
`
${
app
.
name
}
is already open`
))
}
props
.
setApp
(
app
)
props
.
setApp
(
app
)
if
(
!
isRunningApplication
(
app
)
&&
isExecutableApplication
(
app
))
{
if
(
!
isRunningApplication
(
app
)
&&
isExecutableApplication
(
app
))
{
getSession
(
app
)
getSession
(
app
)
.
then
((
session
)
=>
{
.
then
((
session
)
=>
{
props
.
setApp
({
...
app
,
...
session
})
props
.
setApp
({
...
app
,
...
session
})
})
})
.
catch
(
setError
)
.
catch
((
error
)
=>
{
props
.
setApp
(
undefined
)
setError
(
error
)
})
}
}
}
}
// In the case of an error fetching the apps, have the ability to try again.
// In the case of failing to load an app, have the ability to go back to the
// list (where the user can try again if they wish).
if
(
error
)
{
if
(
error
)
{
props
.
setApp
(
undefined
)
return
(
return
(
<
RequestError
<
RequestError
error
=
{
error
}
error
=
{
error
}
onCloseText
=
{
props
.
app
?
"
Go Back
"
:
"
Try Again
"
}
onClose
=
{
():
void
=>
{
onClose
=
{
():
void
=>
{
setError
(
undefined
)
setError
(
undefined
)
if
(
!
props
.
app
)
{
refresh
()
}
}
}
}
}
/>
/>
)
)
}
}
// If an app is currently loading, provide the option to cancel.
if
(
props
.
app
&&
!
props
.
app
.
loaded
)
{
if
(
props
.
app
&&
!
props
.
app
.
loaded
)
{
return
(
return
(
<
div
className
=
"app-loader"
>
<
div
className
=
"app-loader"
>
...
@@ -151,14 +181,16 @@ export const AppLoader: React.FunctionComponent<AppLoaderProps> = (props) => {
...
@@ -151,14 +181,16 @@ export const AppLoader: React.FunctionComponent<AppLoaderProps> = (props) => {
)
)
}
}
// Apps are currently loading.
if
(
!
apps
)
{
if
(
!
apps
)
{
return
(
return
(
<
div
className
=
"app-loader"
>
<
div
className
=
"app-loader"
>
<
div
className
=
"loader"
>
loading
</
div
>
<
div
className
=
"loader"
>
loading
...
</
div
>
</
div
>
</
div
>
)
)
}
}
// Apps have loaded.
return
(
return
(
<>
<>
{
apps
.
map
((
section
,
i
)
=>
(
{
apps
.
map
((
section
,
i
)
=>
(
...
...
src/browser/components/modal.css
浏览文件 @
8cc11d16
...
@@ -100,19 +100,22 @@
...
@@ -100,19 +100,22 @@
width
:
100%
;
width
:
100%
;
}
}
.modal-container
>
.modal
>
.sidebar
{
.sidebar-nav
{
border-right
:
1.5px
solid
rgba
(
0
,
0
,
0
,
0.37
);
display
:
flex
;
display
:
flex
;
flex-direction
:
column
;
flex-direction
:
column
;
justify-content
:
space-between
;
justify-content
:
space-between
;
min-width
:
145px
;
}
}
.
modal-container
>
.modal
>
.sidebar
>
.links
{
.
sidebar-nav
>
.links
{
display
:
flex
;
display
:
flex
;
flex-direction
:
column
;
flex-direction
:
column
;
}
}
.modal-container
>
.modal
>
.sidebar
>
.links
>
.link
{
.sidebar-nav
>
.links
>
.link
{
background-color
:
transparent
;
border
:
none
;
cursor
:
pointer
;
color
:
rgba
(
0
,
0
,
0
,
0.37
);
color
:
rgba
(
0
,
0
,
0
,
0.37
);
font-size
:
1.4em
;
font-size
:
1.4em
;
height
:
31px
;
height
:
31px
;
...
@@ -122,7 +125,7 @@
...
@@ -122,7 +125,7 @@
transition
:
150ms
color
ease
,
150ms
height
ease
,
150ms
margin-bottom
ease
;
transition
:
150ms
color
ease
,
150ms
height
ease
,
150ms
margin-bottom
ease
;
}
}
.
modal-container
>
.modal
>
.sidebar
>
.footer
>
.close
{
.
sidebar-nav
>
.footer
>
.close
{
background
:
transparent
;
background
:
transparent
;
border
:
none
;
border
:
none
;
color
:
#b6b6b6
;
color
:
#b6b6b6
;
...
@@ -130,14 +133,12 @@
...
@@ -130,14 +133,12 @@
width
:
100%
;
width
:
100%
;
}
}
.modal-container
>
.modal
>
.sidebar
>
.footer
>
.close
:hover
{
.sidebar-nav
>
.links
>
.link
[
aria-current
=
"page"
],
.sidebar-nav
>
.links
>
.link
:hover
,
.sidebar-nav
>
.footer
>
.close
:hover
{
color
:
#000
;
color
:
#000
;
}
}
.modal-container
>
.modal
>
.links
>
.link
[
aria-current
=
"page"
]
{
color
:
rgba
(
0
,
0
,
0
,
1
);
}
.modal-container
>
.modal
>
.content
{
.modal-container
>
.modal
>
.content
{
display
:
flex
;
display
:
flex
;
flex
:
1
;
flex
:
1
;
...
@@ -145,3 +146,7 @@
...
@@ -145,3 +146,7 @@
overflow
:
auto
;
overflow
:
auto
;
padding
:
0
20px
;
padding
:
0
20px
;
}
}
.modal-container
>
.modal
>
.sidebar-nav
{
border-right
:
1.5px
solid
rgba
(
0
,
0
,
0
,
0.37
);
}
src/browser/components/modal.tsx
浏览文件 @
8cc11d16
import
{
logger
}
from
"
@coder/logger
"
import
{
logger
}
from
"
@coder/logger
"
import
*
as
React
from
"
react
"
import
*
as
React
from
"
react
"
import
{
NavLink
,
Route
,
RouteComponentProps
,
Switch
}
from
"
react-router-dom
"
import
{
Application
,
isExecutableApplication
}
from
"
../../common/api
"
import
{
Application
,
isExecutableApplication
}
from
"
../../common/api
"
import
{
HttpError
}
from
"
../../common/http
"
import
{
HttpError
}
from
"
../../common/http
"
import
{
RequestError
}
from
"
../components/error
"
import
{
RequestError
}
from
"
../components/error
"
import
{
Browse
}
from
"
../pages/browse
"
import
{
Browse
}
from
"
../pages/browse
"
import
{
Home
}
from
"
../pages/home
"
import
{
Home
}
from
"
../pages/home
"
import
{
Login
}
from
"
../pages/login
"
import
{
Login
}
from
"
../pages/login
"
import
{
Missing
}
from
"
../pages/missing
"
import
{
Open
}
from
"
../pages/open
"
import
{
Open
}
from
"
../pages/open
"
import
{
Recent
}
from
"
../pages/recent
"
import
{
Recent
}
from
"
../pages/recent
"
import
{
Animate
}
from
"
./animate
"
import
{
Animate
}
from
"
./animate
"
...
@@ -19,9 +19,18 @@ export interface ModalProps {
...
@@ -19,9 +19,18 @@ export interface ModalProps {
setError
(
error
?:
HttpError
|
Error
|
string
):
void
setError
(
error
?:
HttpError
|
Error
|
string
):
void
}
}
enum
Section
{
Browse
,
Home
,
Login
,
Open
,
Recent
,
}
export
const
Modal
:
React
.
FunctionComponent
<
ModalProps
>
=
(
props
)
=>
{
export
const
Modal
:
React
.
FunctionComponent
<
ModalProps
>
=
(
props
)
=>
{
const
[
showModal
,
setShowModal
]
=
React
.
useState
<
boolean
>
(
false
)
const
[
showModal
,
setShowModal
]
=
React
.
useState
<
boolean
>
(
false
)
const
[
showBar
,
setShowBar
]
=
React
.
useState
<
boolean
>
(
true
)
const
[
showBar
,
setShowBar
]
=
React
.
useState
<
boolean
>
(
false
)
// TEMP: Will be true.
const
[
section
,
setSection
]
=
React
.
useState
<
Section
>
(
Section
.
Home
)
const
setApp
=
(
app
:
Application
):
void
=>
{
const
setApp
=
(
app
:
Application
):
void
=>
{
setShowModal
(
false
)
setShowModal
(
false
)
...
@@ -36,7 +45,8 @@ export const Modal: React.FunctionComponent<ModalProps> = (props) => {
...
@@ -36,7 +45,8 @@ export const Modal: React.FunctionComponent<ModalProps> = (props) => {
clearTimeout
(
timeout
)
clearTimeout
(
timeout
)
timeout
=
undefined
timeout
=
undefined
}
else
if
(
clientY
<=
30
&&
!
timeout
)
{
}
else
if
(
clientY
<=
30
&&
!
timeout
)
{
timeout
=
setTimeout
(()
=>
setShowBar
(
true
),
1000
)
// TEMP: No bar for now.
// timeout = setTimeout(() => setShowBar(true), 1000)
}
}
}
}
...
@@ -91,39 +101,49 @@ export const Modal: React.FunctionComponent<ModalProps> = (props) => {
...
@@ -91,39 +101,49 @@ export const Modal: React.FunctionComponent<ModalProps> = (props) => {
}
}
},
[
showBar
,
props
.
error
,
showModal
,
props
.
app
])
},
[
showBar
,
props
.
error
,
showModal
,
props
.
app
])
const
content
=
():
React
.
ReactElement
=>
{
if
(
!
props
.
authed
)
{
return
<
Login
/>
}
switch
(
section
)
{
case
Section
.
Recent
:
return
<
Recent
app
=
{
props
.
app
}
setApp
=
{
setApp
}
/>
case
Section
.
Home
:
return
<
Home
app
=
{
props
.
app
}
/>
case
Section
.
Browse
:
return
<
Browse
/>
case
Section
.
Login
:
return
<
Login
/>
case
Section
.
Open
:
return
<
Open
app
=
{
props
.
app
}
setApp
=
{
setApp
}
/>
default
:
return
<
Missing
/>
}
}
return
props
.
error
||
showModal
||
!
props
.
app
||
!
props
.
app
.
loaded
?
(
return
props
.
error
||
showModal
||
!
props
.
app
||
!
props
.
app
.
loaded
?
(
<
div
className
=
"modal-container"
>
<
div
className
=
"modal-container"
>
<
div
className
=
"modal"
>
<
div
className
=
"modal"
>
{
props
.
authed
&&
(
!
props
.
app
||
props
.
app
.
loaded
)
?
(
{
props
.
authed
&&
(
!
props
.
app
||
props
.
app
.
loaded
)
?
(
<
aside
className
=
"sidebar"
>
<
aside
className
=
"sidebar
-nav
"
>
<
nav
className
=
"links"
>
<
nav
className
=
"links"
>
{
!
props
.
authed
?
(
<
NavLink
className
=
"link"
to
=
"/login"
>
Login
</
NavLink
>
)
:
(
undefined
)
}
{
props
.
authed
?
(
{
props
.
authed
?
(
<
NavLink
className
=
"link"
exact
to
=
"/recent/"
>
// TEMP: Remove once we don't auto-load vscode.
<>
<
button
className
=
"link"
onClick
=
{
():
void
=>
setSection
(
Section
.
Recent
)
}
>
Recent
Recent
</
NavLink
>
</
button
>
)
:
(
<
button
className
=
"link"
onClick
=
{
():
void
=>
setSection
(
Section
.
Open
)
}
>
undefined
)
}
{
props
.
authed
?
(
<
NavLink
className
=
"link"
exact
to
=
"/open/"
>
Open
Open
</
NavLink
>
</
button
>
)
:
(
<
button
className
=
"link"
onClick
=
{
():
void
=>
setSection
(
Section
.
Browse
)
}
>
undefined
)
}
{
props
.
authed
?
(
<
NavLink
className
=
"link"
exact
to
=
"/browse/"
>
Browse
Browse
</
NavLink
>
</
button
>
</>
)
:
(
)
:
(
undefined
<
button
className
=
"link"
onClick
=
{
():
void
=>
setSection
(
Section
.
Login
)
}
>
Login
</
button
>
)
}
)
}
</
nav
>
</
nav
>
<
div
className
=
"footer"
>
<
div
className
=
"footer"
>
...
@@ -148,23 +168,7 @@ export const Modal: React.FunctionComponent<ModalProps> = (props) => {
...
@@ -148,23 +168,7 @@ export const Modal: React.FunctionComponent<ModalProps> = (props) => {
}
}
}
}
/>
/>
)
:
(
)
:
(
<
div
className
=
"content"
>
<
div
className
=
"content"
>
{
content
()
}
</
div
>
<
Switch
>
<
Route
path
=
"/login"
component
=
{
Login
}
/>
<
Route
path
=
"/recent"
render
=
{
(
p
:
RouteComponentProps
):
React
.
ReactElement
=>
(
<
Recent
app
=
{
props
.
app
}
setApp
=
{
setApp
}
{
...
p
}
/>
)
}
/>
<
Route
path
=
"/browse"
component
=
{
Browse
}
/>
<
Route
path
=
"/open"
render
=
{
(
p
:
RouteComponentProps
):
React
.
ReactElement
=>
<
Open
app
=
{
props
.
app
}
setApp
=
{
setApp
}
{
...
p
}
/>
}
/>
<
Route
path
=
"/"
component
=
{
Home
}
/>
</
Switch
>
</
div
>
)
}
)
}
</
div
>
</
div
>
</
div
>
</
div
>
...
...
src/browser/index.tsx
浏览文件 @
8cc11d16
import
*
as
React
from
"
react
"
import
*
as
React
from
"
react
"
import
*
as
ReactDOM
from
"
react-dom
"
import
*
as
ReactDOM
from
"
react-dom
"
import
App
from
"
./app
"
import
App
from
"
./app
"
import
{
BrowserRouter
}
from
"
react-router-dom
"
import
{
getOptions
}
from
"
../common/util
"
import
"
./app.css
"
import
"
./app.css
"
import
"
./pages/home.css
"
import
"
./pages/home.css
"
import
"
./pages/login.css
"
import
"
./pages/login.css
"
import
"
./pages/missing.css
"
import
"
./components/error.css
"
import
"
./components/error.css
"
import
"
./components/list.css
"
import
"
./components/list.css
"
import
"
./components/modal.css
"
import
"
./components/modal.css
"
ReactDOM
.
hydrate
(
ReactDOM
.
hydrate
(<
App
options
=
{
getOptions
()
}
/>,
document
.
getElementById
(
"
root
"
))
<
BrowserRouter
>
<
App
/>
</
BrowserRouter
>,
document
.
getElementById
(
"
root
"
)
)
src/browser/pages/browse.tsx
浏览文件 @
8cc11d16
import
*
as
React
from
"
react
"
import
*
as
React
from
"
react
"
import
{
RouteComponentProps
}
from
"
react-router
"
import
{
FilesResponse
}
from
"
../../common/api
"
import
{
FilesResponse
}
from
"
../../common/api
"
import
{
HttpError
}
from
"
../../common/http
"
import
{
HttpError
}
from
"
../../common/http
"
import
{
getFiles
}
from
"
../api
"
import
{
getFiles
}
from
"
../api
"
...
@@ -8,14 +7,14 @@ import { RequestError } from "../components/error"
...
@@ -8,14 +7,14 @@ import { RequestError } from "../components/error"
/**
/**
* File browser.
* File browser.
*/
*/
export
const
Browse
:
React
.
FunctionComponent
<
RouteComponentProps
>
=
(
props
)
=>
{
export
const
Browse
:
React
.
FunctionComponent
=
(
props
)
=>
{
const
[
response
,
setResponse
]
=
React
.
useState
<
FilesResponse
>
()
const
[
response
,
setResponse
]
=
React
.
useState
<
FilesResponse
>
()
const
[
error
,
setError
]
=
React
.
useState
<
HttpError
>
()
const
[
error
,
setError
]
=
React
.
useState
<
HttpError
>
()
React
.
useEffect
(()
=>
{
React
.
useEffect
(()
=>
{
getFiles
()
getFiles
()
.
then
(
setResponse
)
.
then
(
setResponse
)
.
catch
(
(
e
)
=>
setError
(
e
.
message
)
)
.
catch
(
setError
)
},
[
props
])
},
[
props
])
return
(
return
(
...
...
src/browser/pages/home.tsx
浏览文件 @
8cc11d16
import
*
as
React
from
"
react
"
import
*
as
React
from
"
react
"
import
{
RouteComponentProps
}
from
"
react-router
"
import
{
Application
}
from
"
../../common/api
"
import
{
authenticate
}
from
"
../api
"
import
{
authenticate
}
from
"
../api
"
export
const
Home
:
React
.
FunctionComponent
<
RouteComponentProps
>
=
(
props
)
=>
{
export
interface
HomeProps
{
app
?:
Application
}
export
const
Home
:
React
.
FunctionComponent
<
HomeProps
>
=
(
props
)
=>
{
React
.
useEffect
(()
=>
{
React
.
useEffect
(()
=>
{
authenticate
()
authenticate
().
catch
(()
=>
undefined
)
.
then
(()
=>
{
// TEMP: Always redirect to VS Code.
props
.
history
.
push
(
"
./vscode/
"
)
})
.
catch
(()
=>
{
props
.
history
.
push
(
"
./login/
"
)
})
},
[])
},
[])
return
(
return
(
<
div
className
=
"orientation-guide"
>
<
div
className
=
"orientation-guide"
>
<
div
className
=
"welcome"
>
Welcome to code-server.
</
div
>
<
div
className
=
"welcome"
>
Welcome to code-server.
</
div
>
{
props
.
app
&&
!
props
.
app
.
loaded
?
<
div
className
=
"loader"
>
loading...
</
div
>
:
undefined
}
</
div
>
</
div
>
)
)
}
}
src/browser/pages/login.css
浏览文件 @
8cc11d16
...
@@ -4,9 +4,7 @@
...
@@ -4,9 +4,7 @@
display
:
flex
;
display
:
flex
;
flex
:
1
;
flex
:
1
;
flex-direction
:
column
;
flex-direction
:
column
;
font-weight
:
700
;
justify-content
:
center
;
justify-content
:
center
;
text-transform
:
uppercase
;
}
}
.login-form
>
.field
{
.login-form
>
.field
{
...
@@ -16,13 +14,13 @@
...
@@ -16,13 +14,13 @@
}
}
.login-form
>
.field-error
{
.login-form
>
.field-error
{
margin-top
:
1
0px
;
margin-top
:
1
em
;
}
}
.login-form
>
.field
>
.input
{
.login-form
>
.field
>
.input
{
border
:
1px
solid
#b6b6b6
;
border
:
1px
solid
#b6b6b6
;
box-sizing
:
border-box
;
box-sizing
:
border-box
;
padding
:
1
0px
;
padding
:
1
em
;
flex
:
1
;
flex
:
1
;
}
}
...
@@ -31,5 +29,11 @@
...
@@ -31,5 +29,11 @@
border
:
1px
solid
#b6b6b6
;
border
:
1px
solid
#b6b6b6
;
box-sizing
:
border-box
;
box-sizing
:
border-box
;
margin-left
:
-1px
;
margin-left
:
-1px
;
padding
:
10px
20px
;
padding
:
1em
2em
;
}
.login-header
{
align-items
:
center
;
color
:
#b6b6b6
;
margin-bottom
:
1em
;
}
}
src/browser/pages/login.tsx
浏览文件 @
8cc11d16
import
*
as
React
from
"
react
"
import
*
as
React
from
"
react
"
import
{
RouteComponentProps
}
from
"
react-router
"
import
{
HttpError
}
from
"
../../common/http
"
import
{
HttpError
}
from
"
../../common/http
"
import
{
authenticate
}
from
"
../api
"
import
{
authenticate
}
from
"
../api
"
import
{
FieldError
}
from
"
../components/error
"
import
{
FieldError
}
from
"
../components/error
"
...
@@ -7,35 +6,25 @@ import { FieldError } from "../components/error"
...
@@ -7,35 +6,25 @@ import { FieldError } from "../components/error"
/**
/**
* Login page. Will redirect on success.
* Login page. Will redirect on success.
*/
*/
export
const
Login
:
React
.
FunctionComponent
<
RouteComponentProps
>
=
(
props
)
=>
{
export
const
Login
:
React
.
FunctionComponent
=
(
)
=>
{
const
[
password
,
setPassword
]
=
React
.
useState
<
string
>
(
""
)
const
[
password
,
setPassword
]
=
React
.
useState
<
string
>
(
""
)
const
[
error
,
setError
]
=
React
.
useState
<
HttpError
>
()
const
[
error
,
setError
]
=
React
.
useState
<
HttpError
>
()
function
redirect
():
void
{
// TEMP: Always redirect to VS Code.
console
.
log
(
"
is authed
"
)
props
.
history
.
push
(
"
../vscode/
"
)
// const params = new URLSearchParams(window.location.search)
// props.history.push(params.get("to") || "/")
}
async
function
handleSubmit
(
event
:
React
.
FormEvent
<
HTMLFormElement
>
):
Promise
<
void
>
{
async
function
handleSubmit
(
event
:
React
.
FormEvent
<
HTMLFormElement
>
):
Promise
<
void
>
{
event
.
preventDefault
()
event
.
preventDefault
()
authenticate
({
password
})
authenticate
({
password
}).
catch
(
setError
)
.
then
(
redirect
)
.
catch
(
setError
)
}
}
React
.
useEffect
(()
=>
{
React
.
useEffect
(()
=>
{
authenticate
()
authenticate
().
catch
(()
=>
undefined
)
.
then
(
redirect
)
.
catch
(()
=>
{
// Do nothing; we're already at the login page.
})
},
[])
},
[])
return
(
return
(
<
form
className
=
"login-form"
onSubmit
=
{
handleSubmit
}
>
<
form
className
=
"login-form"
onSubmit
=
{
handleSubmit
}
>
<
div
className
=
"login-header"
>
<
div
className
=
"main"
>
Welcome to code-server
</
div
>
<
div
className
=
"sub"
>
Please log in below
</
div
>
</
div
>
<
div
className
=
"field"
>
<
div
className
=
"field"
>
<
input
<
input
autoFocus
autoFocus
...
...
src/browser/pages/missing.css
0 → 100644
浏览文件 @
8cc11d16
.missing-message
{
align-items
:
center
;
color
:
#b6b6b6
;
display
:
flex
;
flex
:
1
;
flex-direction
:
column
;
justify-content
:
center
;
}
src/browser/pages/missing.tsx
0 → 100644
浏览文件 @
8cc11d16
import
*
as
React
from
"
react
"
export
const
Missing
:
React
.
FunctionComponent
=
()
=>
{
return
(
<
div
className
=
"missing-message"
>
<
div
className
=
"message"
>
404
</
div
>
</
div
>
)
}
src/common/api.ts
浏览文件 @
8cc11d16
export
interface
Application
{
export
interface
Application
{
readonly
comment
?:
string
readonly
comment
?:
string
readonly
directory
?:
string
readonly
directory
?:
string
readonly
embedPath
?:
string
readonly
exec
?:
string
readonly
exec
?:
string
readonly
icon
?:
string
readonly
icon
?:
string
readonly
loaded
?:
boolean
readonly
loaded
?:
boolean
...
...
src/common/util.ts
浏览文件 @
8cc11d16
import
{
logger
}
from
"
@coder/logger
"
import
{
logger
}
from
"
@coder/logger
"
import
{
Application
}
from
"
../common/api
"
export
interface
Options
{
export
interface
Options
{
app
?:
Application
authed
?:
boolean
logLevel
?:
number
logLevel
?:
number
}
}
...
@@ -27,6 +30,9 @@ export const generateUuid = (length = 24): string => {
...
@@ -27,6 +30,9 @@ export const generateUuid = (length = 24): string => {
* Get options embedded in the HTML from the server.
* Get options embedded in the HTML from the server.
*/
*/
export
const
getOptions
=
<
T
extends
Options
>
():
T
=>
{
export
const
getOptions
=
<
T
extends
Options
>
():
T
=>
{
if
(
typeof
document
===
"
undefined
"
)
{
return
{}
as
T
}
const
el
=
document
.
getElementById
(
"
coder-options
"
)
const
el
=
document
.
getElementById
(
"
coder-options
"
)
try
{
try
{
if
(
!
el
)
{
if
(
!
el
)
{
...
@@ -46,3 +52,10 @@ export const getOptions = <T extends Options>(): T => {
...
@@ -46,3 +52,10 @@ export const getOptions = <T extends Options>(): T => {
return
{}
as
T
return
{}
as
T
}
}
}
}
/**
* Remove extra slashes in a URL.
*/
export
const
normalize
=
(
url
:
string
,
keepTrailing
=
false
):
string
=>
{
return
url
.
replace
(
/
\/\/
+/g
,
"
/
"
).
replace
(
/
\/
+$/
,
keepTrailing
?
"
/
"
:
""
)
}
src/node/api/server.ts
浏览文件 @
8cc11d16
...
@@ -151,6 +151,7 @@ export class ApiHttpProvider extends HttpProvider {
...
@@ -151,6 +151,7 @@ export class ApiHttpProvider extends HttpProvider {
{
{
name
:
"
VS Code
"
,
name
:
"
VS Code
"
,
path
:
"
/vscode
"
,
path
:
"
/vscode
"
,
embedPath
:
"
/vscode-embed
"
,
},
},
],
],
},
},
...
...
src/node/app/server.tsx
浏览文件 @
8cc11d16
import
{
logger
}
from
"
@coder/logger
"
import
{
logger
}
from
"
@coder/logger
"
import
*
as
http
from
"
http
"
import
*
as
querystring
from
"
querystring
"
import
*
as
React
from
"
react
"
import
*
as
React
from
"
react
"
import
*
as
ReactDOMServer
from
"
react-dom/server
"
import
*
as
ReactDOMServer
from
"
react-dom/server
"
import
*
as
ReactRouterDOM
from
"
react-router-dom
"
import
App
from
"
../../browser/app
"
import
App
from
"
../../browser/app
"
import
{
Options
}
from
"
../../common/util
"
import
{
HttpProvider
,
HttpResponse
}
from
"
../http
"
import
{
HttpProvider
,
HttpResponse
}
from
"
../http
"
/**
/**
* Top-level and fallback HTTP provider.
* Top-level and fallback HTTP provider.
*/
*/
export
class
MainHttpProvider
extends
HttpProvider
{
export
class
MainHttpProvider
extends
HttpProvider
{
public
async
handleRequest
(
base
:
string
,
requestPath
:
string
):
Promise
<
HttpResponse
|
undefined
>
{
public
async
handleRequest
(
base
:
string
,
requestPath
:
string
,
_query
:
querystring
.
ParsedUrlQuery
,
request
:
http
.
IncomingMessage
):
Promise
<
HttpResponse
|
undefined
>
{
if
(
base
===
"
/static
"
)
{
if
(
base
===
"
/static
"
)
{
const
response
=
await
this
.
getResource
(
this
.
rootPath
,
requestPath
)
const
response
=
await
this
.
getResource
(
this
.
rootPath
,
requestPath
)
if
(
this
.
options
.
commit
&&
this
.
options
.
commit
!==
"
development
"
)
{
response
.
cache
=
true
response
.
cache
=
true
}
return
response
return
response
}
}
// TEMP: Auto-load VS Code for now. In future versions we'll need to check
// the URL for the appropriate application to load, if any.
const
app
=
{
name
:
"
VS Code
"
,
path
:
"
/
"
,
embedPath
:
"
/vscode-embed
"
,
}
const
options
:
Options
=
{
app
,
authed
:
!!
this
.
authenticated
(
request
),
logLevel
:
logger
.
level
,
}
const
response
=
await
this
.
getUtf8Resource
(
this
.
rootPath
,
"
src/browser/index.html
"
)
const
response
=
await
this
.
getUtf8Resource
(
this
.
rootPath
,
"
src/browser/index.html
"
)
response
.
content
=
response
.
content
response
.
content
=
response
.
content
.
replace
(
/{{COMMIT}}/g
,
""
)
// TODO
.
replace
(
/{{COMMIT}}/g
,
this
.
options
.
commit
||
"
development
"
)
.
replace
(
/"{{OPTIONS}}"/g
,
`'
${
JSON
.
stringify
({
logLevel
:
logger
.
level
})}
'`
)
.
replace
(
/"{{OPTIONS}}"/g
,
`'
${
JSON
.
stringify
(
options
)}
'`
)
.
replace
(
.
replace
(
/{{COMPONENT}}/g
,
ReactDOMServer
.
renderToString
(<
App
options
=
{
options
}
/>))
/{{COMPONENT}}/g
,
ReactDOMServer
.
renderToString
(
<
ReactRouterDOM
.
StaticRouter
location
=
{
base
}
>
<
App
/>
</
ReactRouterDOM
.
StaticRouter
>
)
)
return
response
return
response
}
}
...
...
src/node/entry.ts
浏览文件 @
8cc11d16
...
@@ -23,25 +23,32 @@ const main = async (args: Args = {}): Promise<void> => {
...
@@ -23,25 +23,32 @@ const main = async (args: Args = {}): Promise<void> => {
const
auth
=
args
.
auth
||
AuthType
.
Password
const
auth
=
args
.
auth
||
AuthType
.
Password
const
originalPassword
=
auth
===
AuthType
.
Password
&&
(
process
.
env
.
PASSWORD
||
(
await
generatePassword
()))
const
originalPassword
=
auth
===
AuthType
.
Password
&&
(
process
.
env
.
PASSWORD
||
(
await
generatePassword
()))
let
commit
=
"
development
"
try
{
commit
=
require
(
"
../../package.json
"
).
commit
}
catch
(
error
)
{
logger
.
warn
(
error
.
message
)
}
// Spawn the main HTTP server.
// Spawn the main HTTP server.
const
options
=
{
const
options
=
{
auth
,
basePath
:
args
[
"
base-path
"
],
basePath
:
args
[
"
base-path
"
],
cert
:
args
.
cert
,
cert
:
args
.
cert
,
certKey
:
args
[
"
cert-key
"
],
certKey
:
args
[
"
cert-key
"
],
commit
,
host
:
args
.
host
||
(
args
.
auth
===
AuthType
.
Password
&&
typeof
args
.
cert
!==
"
undefined
"
?
"
0.0.0.0
"
:
"
localhost
"
),
host
:
args
.
host
||
(
args
.
auth
===
AuthType
.
Password
&&
typeof
args
.
cert
!==
"
undefined
"
?
"
0.0.0.0
"
:
"
localhost
"
),
password
:
originalPassword
?
hash
(
originalPassword
)
:
undefined
,
port
:
typeof
args
.
port
!==
"
undefined
"
?
parseInt
(
args
.
port
,
10
)
:
8080
,
port
:
typeof
args
.
port
!==
"
undefined
"
?
parseInt
(
args
.
port
,
10
)
:
8080
,
socket
:
args
.
socket
,
socket
:
args
.
socket
,
auth
,
password
:
originalPassword
?
hash
(
originalPassword
)
:
undefined
,
}
}
if
(
!
options
.
cert
&&
typeof
options
.
cert
!==
"
undefined
"
)
{
if
(
!
options
.
cert
&&
typeof
options
.
cert
!==
"
undefined
"
)
{
const
{
cert
,
certKey
}
=
await
generateCertificate
()
const
{
cert
,
certKey
}
=
await
generateCertificate
()
options
.
cert
=
cert
options
.
cert
=
cert
options
.
certKey
=
certKey
options
.
certKey
=
certKey
}
}
const
httpServer
=
new
HttpServer
(
options
)
// Register all the providers.
const
httpServer
=
new
HttpServer
(
options
)
httpServer
.
registerHttpProvider
(
"
/
"
,
MainHttpProvider
)
httpServer
.
registerHttpProvider
(
"
/
"
,
MainHttpProvider
)
httpServer
.
registerHttpProvider
(
"
/api
"
,
ApiHttpProvider
,
httpServer
)
httpServer
.
registerHttpProvider
(
"
/api
"
,
ApiHttpProvider
,
httpServer
)
httpServer
.
registerHttpProvider
(
"
/vscode-embed
"
,
VscodeHttpProvider
,
[])
httpServer
.
registerHttpProvider
(
"
/vscode-embed
"
,
VscodeHttpProvider
,
[])
...
...
src/node/http.ts
浏览文件 @
8cc11d16
...
@@ -12,8 +12,8 @@ import * as tarFs from "tar-fs"
...
@@ -12,8 +12,8 @@ import * as tarFs from "tar-fs"
import
*
as
tls
from
"
tls
"
import
*
as
tls
from
"
tls
"
import
*
as
url
from
"
url
"
import
*
as
url
from
"
url
"
import
{
HttpCode
,
HttpError
}
from
"
../common/http
"
import
{
HttpCode
,
HttpError
}
from
"
../common/http
"
import
{
plural
,
split
}
from
"
../common/util
"
import
{
normalize
,
plural
,
split
}
from
"
../common/util
"
import
{
getMediaMime
,
normalize
,
xdgLocalDir
}
from
"
./util
"
import
{
getMediaMime
,
xdgLocalDir
}
from
"
./util
"
export
type
Cookies
=
{
[
key
:
string
]:
string
[]
|
undefined
}
export
type
Cookies
=
{
[
key
:
string
]:
string
[]
|
undefined
}
export
type
PostData
=
{
[
key
:
string
]:
string
|
string
[]
|
undefined
}
export
type
PostData
=
{
[
key
:
string
]:
string
|
string
[]
|
undefined
}
...
@@ -92,6 +92,7 @@ export interface HttpServerOptions {
...
@@ -92,6 +92,7 @@ export interface HttpServerOptions {
readonly
basePath
?:
string
readonly
basePath
?:
string
readonly
cert
?:
string
readonly
cert
?:
string
readonly
certKey
?:
string
readonly
certKey
?:
string
readonly
commit
?:
string
readonly
host
?:
string
readonly
host
?:
string
readonly
password
?:
string
readonly
password
?:
string
readonly
port
?:
number
readonly
port
?:
number
...
@@ -111,6 +112,7 @@ export interface HttpProviderOptions {
...
@@ -111,6 +112,7 @@ export interface HttpProviderOptions {
readonly
base
:
string
readonly
base
:
string
readonly
auth
:
AuthType
readonly
auth
:
AuthType
readonly
password
?:
string
readonly
password
?:
string
readonly
commit
?:
string
}
}
/**
/**
...
@@ -120,7 +122,7 @@ export interface HttpProviderOptions {
...
@@ -120,7 +122,7 @@ export interface HttpProviderOptions {
export
abstract
class
HttpProvider
{
export
abstract
class
HttpProvider
{
protected
readonly
rootPath
=
path
.
resolve
(
__dirname
,
"
../..
"
)
protected
readonly
rootPath
=
path
.
resolve
(
__dirname
,
"
../..
"
)
public
constructor
(
pr
ivate
readonly
options
:
HttpProviderOptions
)
{}
public
constructor
(
pr
otected
readonly
options
:
HttpProviderOptions
)
{}
public
dispose
():
void
{
public
dispose
():
void
{
// No default behavior.
// No default behavior.
...
@@ -403,6 +405,7 @@ export class HttpServer {
...
@@ -403,6 +405,7 @@ export class HttpServer {
{
{
auth
:
this
.
options
.
auth
||
AuthType
.
None
,
auth
:
this
.
options
.
auth
||
AuthType
.
None
,
base
:
endpoint
,
base
:
endpoint
,
commit
:
this
.
options
.
commit
,
password
:
this
.
options
.
password
,
password
:
this
.
options
.
password
,
},
},
a1
a1
...
...
src/node/util.ts
浏览文件 @
8cc11d16
...
@@ -207,10 +207,3 @@ export function extend(...args: any[]): any {
...
@@ -207,10 +207,3 @@ export function extend(...args: any[]): any {
}
}
return
c
return
c
}
}
/**
* Remove extra and trailing slashes in a URL.
*/
export
const
normalize
=
(
url
:
string
):
string
=>
{
return
url
.
replace
(
/
\/\/
+/g
,
"
/
"
).
replace
(
/
\/
+$/
,
""
)
}
test/util.test.ts
浏览文件 @
8cc11d16
import
*
as
assert
from
"
assert
"
import
*
as
assert
from
"
assert
"
import
{
extend
,
normalize
}
from
"
../src/node/util
"
import
{
normalize
}
from
"
../src/common/util
"
import
{
extend
}
from
"
../src/node/util
"
describe
(
"
util
"
,
()
=>
{
describe
(
"
util
"
,
()
=>
{
describe
(
"
extend
"
,
()
=>
{
describe
(
"
extend
"
,
()
=>
{
...
@@ -45,5 +46,10 @@ describe("util", () => {
...
@@ -45,5 +46,10 @@ describe("util", () => {
it
(
"
should remove trailing slashes
"
,
()
=>
{
it
(
"
should remove trailing slashes
"
,
()
=>
{
assert
.
equal
(
normalize
(
"
qux///
"
),
"
qux
"
)
assert
.
equal
(
normalize
(
"
qux///
"
),
"
qux
"
)
})
})
it
(
"
should preserve trailing slash if it exists
"
,
()
=>
{
assert
.
equal
(
normalize
(
"
qux///
"
,
true
),
"
qux/
"
)
assert
.
equal
(
normalize
(
"
qux
"
,
true
),
"
qux
"
)
})
})
})
})
})
yarn.lock
浏览文件 @
8cc11d16
...
@@ -714,7 +714,7 @@
...
@@ -714,7 +714,7 @@
levenary "^1.1.1"
levenary "^1.1.1"
semver "^5.5.0"
semver "^5.5.0"
"@babel/runtime@^7.
1.2", "@babel/runtime@^7.4.0", "@babel/runtime@^7.
4.4", "@babel/runtime@^7.6.3":
"@babel/runtime@^7.4.4", "@babel/runtime@^7.6.3":
version "7.8.4"
version "7.8.4"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.8.4.tgz#d79f5a2040f7caa24d53e563aad49cbc05581308"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.8.4.tgz#d79f5a2040f7caa24d53e563aad49cbc05581308"
integrity sha512-neAp3zt80trRVBI1x0azq6c57aNBqYZH8KhMm3TaB7wEI5Q4A2SHfBHE8w9gOhI/lrqxtEbXZgQIrHP+wvSGwQ==
integrity sha512-neAp3zt80trRVBI1x0azq6c57aNBqYZH8KhMm3TaB7wEI5Q4A2SHfBHE8w9gOhI/lrqxtEbXZgQIrHP+wvSGwQ==
...
@@ -881,10 +881,13 @@
...
@@ -881,10 +881,13 @@
dependencies:
dependencies:
"@types/node" "*"
"@types/node" "*"
"@types/history@*":
"@types/hookrouter@^2.2.1":
version "4.7.5"
version "2.2.1"
resolved "https://registry.yarnpkg.com/@types/history/-/history-4.7.5.tgz#527d20ef68571a4af02ed74350164e7a67544860"
resolved "https://registry.yarnpkg.com/@types/hookrouter/-/hookrouter-2.2.1.tgz#0c69e671957b48ade9e042612faf3fc833a3fd59"
integrity sha512-wLD/Aq2VggCJXSjxEwrMafIP51Z+13H78nXIX0ABEuIGhmB5sNGbR113MOKo+yfw+RDo1ZU3DM6yfnnRF/+ouw==
integrity sha512-C4Ae6yf8vE4TEKZa0EpP2o85UMVHKsZeJwT0oWiQ1QkNBbkQ8bk5A+qWS25Uect9r1Uivz/dnSg6v4WwzFjgrg==
dependencies:
"@types/react" "*"
csstype "^2.2.0"
"@types/json-schema@^7.0.3":
"@types/json-schema@^7.0.3":
version "7.0.4"
version "7.0.4"
...
@@ -952,23 +955,6 @@
...
@@ -952,23 +955,6 @@
dependencies:
dependencies:
"@types/react" "*"
"@types/react" "*"
"@types/react-router-dom@^5.1.3":
version "5.1.3"
resolved "https://registry.yarnpkg.com/@types/react-router-dom/-/react-router-dom-5.1.3.tgz#b5d28e7850bd274d944c0fbbe5d57e6b30d71196"
integrity sha512-pCq7AkOvjE65jkGS5fQwQhvUp4+4PVD9g39gXLZViP2UqFiFzsEpB3PKf0O6mdbKsewSK8N14/eegisa/0CwnA==
dependencies:
"@types/history" "*"
"@types/react" "*"
"@types/react-router" "*"
"@types/react-router@*":
version "5.1.4"
resolved "https://registry.yarnpkg.com/@types/react-router/-/react-router-5.1.4.tgz#7d70bd905543cb6bcbdcc6bd98902332054f31a6"
integrity sha512-PZtnBuyfL07sqCJvGg3z+0+kt6fobc/xmle08jBiezLS8FrmGeiGkJnuxL/8Zgy9L83ypUhniV5atZn/L8n9MQ==
dependencies:
"@types/history" "*"
"@types/react" "*"
"@types/react@*", "@types/react@^16.9.18":
"@types/react@*", "@types/react@^16.9.18":
version "16.9.19"
version "16.9.19"
resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.19.tgz#c842aa83ea490007d29938146ff2e4d9e4360c40"
resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.19.tgz#c842aa83ea490007d29938146ff2e4d9e4360c40"
...
@@ -3460,11 +3446,6 @@ growl@1.10.5:
...
@@ -3460,11 +3446,6 @@ growl@1.10.5:
resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e"
resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e"
integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==
integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==
gud@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/gud/-/gud-1.0.0.tgz#a489581b17e6a70beca9abe3ae57de7a499852c0"
integrity sha512-zGEOVKFM5sVPPrYs7J5/hYEw2Pof8KCyOwyhG8sAF26mCAeUFAcYPu1mwB7hhpIP29zOIBaDqwuHdLp0jvZXjw==
har-schema@^2.0.0:
har-schema@^2.0.0:
version "2.0.0"
version "2.0.0"
resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92"
resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92"
...
@@ -3574,18 +3555,6 @@ hex-color-regex@^1.1.0:
...
@@ -3574,18 +3555,6 @@ hex-color-regex@^1.1.0:
resolved "https://registry.yarnpkg.com/hex-color-regex/-/hex-color-regex-1.1.0.tgz#4c06fccb4602fe2602b3c93df82d7e7dbf1a8a8e"
resolved "https://registry.yarnpkg.com/hex-color-regex/-/hex-color-regex-1.1.0.tgz#4c06fccb4602fe2602b3c93df82d7e7dbf1a8a8e"
integrity sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ==
integrity sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ==
history@^4.9.0:
version "4.10.1"
resolved "https://registry.yarnpkg.com/history/-/history-4.10.1.tgz#33371a65e3a83b267434e2b3f3b1b4c58aad4cf3"
integrity sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew==
dependencies:
"@babel/runtime" "^7.1.2"
loose-envify "^1.2.0"
resolve-pathname "^3.0.0"
tiny-invariant "^1.0.2"
tiny-warning "^1.0.0"
value-equal "^1.0.1"
hmac-drbg@^1.0.0:
hmac-drbg@^1.0.0:
version "1.0.1"
version "1.0.1"
resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1"
resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1"
...
@@ -3595,12 +3564,10 @@ hmac-drbg@^1.0.0:
...
@@ -3595,12 +3564,10 @@ hmac-drbg@^1.0.0:
minimalistic-assert "^1.0.0"
minimalistic-assert "^1.0.0"
minimalistic-crypto-utils "^1.0.1"
minimalistic-crypto-utils "^1.0.1"
hoist-non-react-statics@^3.1.0:
hookrouter@^1.2.3:
version "3.3.2"
version "1.2.3"
resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45"
resolved "https://registry.yarnpkg.com/hookrouter/-/hookrouter-1.2.3.tgz#a65599a1be376b51734caf7c4f7f8aba59bb2c77"
integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==
integrity sha512-n0mqEBGgXIxYRNMHlwCzoyTOk0OB5Es3jwUyA3+2l5nte/52n0CMMj1bmoCabC8K43YTUEr0zzexTBfo//tq2Q==
dependencies:
react-is "^16.7.0"
hosted-git-info@^2.1.4:
hosted-git-info@^2.1.4:
version "2.8.5"
version "2.8.5"
...
@@ -4461,7 +4428,7 @@ longest-streak@^2.0.1:
...
@@ -4461,7 +4428,7 @@ longest-streak@^2.0.1:
resolved "https://registry.yarnpkg.com/longest-streak/-/longest-streak-2.0.4.tgz#b8599957da5b5dab64dee3fe316fa774597d90e4"
resolved "https://registry.yarnpkg.com/longest-streak/-/longest-streak-2.0.4.tgz#b8599957da5b5dab64dee3fe316fa774597d90e4"
integrity sha512-vM6rUVCVUJJt33bnmHiZEvr7wPT78ztX7rojL+LW51bHtLh6HTjx84LA5W4+oa6aKEJA7jJu5LR6vQRBpA5DVg==
integrity sha512-vM6rUVCVUJJt33bnmHiZEvr7wPT78ztX7rojL+LW51bHtLh6HTjx84LA5W4+oa6aKEJA7jJu5LR6vQRBpA5DVg==
loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.
2.0, loose-envify@^1.3.1, loose-envify@^1.
4.0:
loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0:
version "1.4.0"
version "1.4.0"
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==
integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==
...
@@ -4643,15 +4610,6 @@ min-indent@^1.0.0:
...
@@ -4643,15 +4610,6 @@ min-indent@^1.0.0:
resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.0.tgz#cfc45c37e9ec0d8f0a0ec3dd4ef7f7c3abe39256"
resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.0.tgz#cfc45c37e9ec0d8f0a0ec3dd4ef7f7c3abe39256"
integrity sha1-z8RcN+nsDY8KDsPdTvf3w6vjklY=
integrity sha1-z8RcN+nsDY8KDsPdTvf3w6vjklY=
mini-create-react-context@^0.3.0:
version "0.3.2"
resolved "https://registry.yarnpkg.com/mini-create-react-context/-/mini-create-react-context-0.3.2.tgz#79fc598f283dd623da8e088b05db8cddab250189"
integrity sha512-2v+OeetEyliMt5VHMXsBhABoJ0/M4RCe7fatd/fBy6SMiKazUSEt3gxxypfnk2SHMkdBYvorHRoQxuGoiwbzAw==
dependencies:
"@babel/runtime" "^7.4.0"
gud "^1.0.0"
tiny-warning "^1.0.2"
minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1:
minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1:
version "1.0.1"
version "1.0.1"
resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7"
resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7"
...
@@ -5342,13 +5300,6 @@ path-platform@~0.11.15:
...
@@ -5342,13 +5300,6 @@ path-platform@~0.11.15:
resolved "https://registry.yarnpkg.com/path-platform/-/path-platform-0.11.15.tgz#e864217f74c36850f0852b78dc7bf7d4a5721bf2"
resolved "https://registry.yarnpkg.com/path-platform/-/path-platform-0.11.15.tgz#e864217f74c36850f0852b78dc7bf7d4a5721bf2"
integrity sha1-6GQhf3TDaFDwhSt43Hv31KVyG/I=
integrity sha1-6GQhf3TDaFDwhSt43Hv31KVyG/I=
path-to-regexp@^1.7.0:
version "1.8.0"
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.8.0.tgz#887b3ba9d84393e87a0a0b9f4cb756198b53548a"
integrity sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==
dependencies:
isarray "0.0.1"
path-type@^2.0.0:
path-type@^2.0.0:
version "2.0.0"
version "2.0.0"
resolved "https://registry.yarnpkg.com/path-type/-/path-type-2.0.0.tgz#f012ccb8415b7096fc2daa1054c3d72389594c73"
resolved "https://registry.yarnpkg.com/path-type/-/path-type-2.0.0.tgz#f012ccb8415b7096fc2daa1054c3d72389594c73"
...
@@ -6031,40 +5982,11 @@ react-dom@^16.12.0:
...
@@ -6031,40 +5982,11 @@ react-dom@^16.12.0:
prop-types "^15.6.2"
prop-types "^15.6.2"
scheduler "^0.18.0"
scheduler "^0.18.0"
react-is@^16.
6.0, react-is@^16.7.0, react-is@^16.
8.1:
react-is@^16.8.1:
version "16.12.0"
version "16.12.0"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.12.0.tgz#2cc0fe0fba742d97fd527c42a13bec4eeb06241c"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.12.0.tgz#2cc0fe0fba742d97fd527c42a13bec4eeb06241c"
integrity sha512-rPCkf/mWBtKc97aLL9/txD8DZdemK0vkA3JMLShjlJB3Pj3s+lpf1KaBzMfQrAmhMQB0n1cU/SUGgKKBCe837Q==
integrity sha512-rPCkf/mWBtKc97aLL9/txD8DZdemK0vkA3JMLShjlJB3Pj3s+lpf1KaBzMfQrAmhMQB0n1cU/SUGgKKBCe837Q==
react-router-dom@^5.1.2:
version "5.1.2"
resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-5.1.2.tgz#06701b834352f44d37fbb6311f870f84c76b9c18"
integrity sha512-7BPHAaIwWpZS074UKaw1FjVdZBSVWEk8IuDXdB+OkLb8vd/WRQIpA4ag9WQk61aEfQs47wHyjWUoUGGZxpQXew==
dependencies:
"@babel/runtime" "^7.1.2"
history "^4.9.0"
loose-envify "^1.3.1"
prop-types "^15.6.2"
react-router "5.1.2"
tiny-invariant "^1.0.2"
tiny-warning "^1.0.0"
react-router@5.1.2:
version "5.1.2"
resolved "https://registry.yarnpkg.com/react-router/-/react-router-5.1.2.tgz#6ea51d789cb36a6be1ba5f7c0d48dd9e817d3418"
integrity sha512-yjEuMFy1ONK246B+rsa0cUam5OeAQ8pyclRDgpxuSCrAlJ1qN9uZ5IgyKC7gQg0w8OM50NXHEegPh/ks9YuR2A==
dependencies:
"@babel/runtime" "^7.1.2"
history "^4.9.0"
hoist-non-react-statics "^3.1.0"
loose-envify "^1.3.1"
mini-create-react-context "^0.3.0"
path-to-regexp "^1.7.0"
prop-types "^15.6.2"
react-is "^16.6.0"
tiny-invariant "^1.0.2"
tiny-warning "^1.0.0"
react@^16.12.0:
react@^16.12.0:
version "16.12.0"
version "16.12.0"
resolved "https://registry.yarnpkg.com/react/-/react-16.12.0.tgz#0c0a9c6a142429e3614834d5a778e18aa78a0b83"
resolved "https://registry.yarnpkg.com/react/-/react-16.12.0.tgz#0c0a9c6a142429e3614834d5a778e18aa78a0b83"
...
@@ -6402,11 +6324,6 @@ resolve-from@^5.0.0:
...
@@ -6402,11 +6324,6 @@ resolve-from@^5.0.0:
resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69"
resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69"
integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==
integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==
resolve-pathname@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/resolve-pathname/-/resolve-pathname-3.0.0.tgz#99d02224d3cf263689becbb393bc560313025dcd"
integrity sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng==
resolve-url@^0.2.1:
resolve-url@^0.2.1:
version "0.2.1"
version "0.2.1"
resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a"
resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a"
...
@@ -7321,16 +7238,6 @@ tiny-inflate@^1.0.0:
...
@@ -7321,16 +7238,6 @@ tiny-inflate@^1.0.0:
resolved "https://registry.yarnpkg.com/tiny-inflate/-/tiny-inflate-1.0.3.tgz#122715494913a1805166aaf7c93467933eea26c4"
resolved "https://registry.yarnpkg.com/tiny-inflate/-/tiny-inflate-1.0.3.tgz#122715494913a1805166aaf7c93467933eea26c4"
integrity sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==
integrity sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==
tiny-invariant@^1.0.2:
version "1.1.0"
resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.1.0.tgz#634c5f8efdc27714b7f386c35e6760991d230875"
integrity sha512-ytxQvrb1cPc9WBEI/HSeYYoGD0kWnGEOR8RY6KomWLBVhqz0RgTwVO9dLrGz7dC+nN9llyI7OKAgRq8Vq4ZBSw==
tiny-warning@^1.0.0, tiny-warning@^1.0.2:
version "1.0.3"
resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754"
integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==
tmp@^0.0.33:
tmp@^0.0.33:
version "0.0.33"
version "0.0.33"
resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9"
resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9"
...
@@ -7763,11 +7670,6 @@ validate-npm-package-license@^3.0.1:
...
@@ -7763,11 +7670,6 @@ validate-npm-package-license@^3.0.1:
spdx-correct "^3.0.0"
spdx-correct "^3.0.0"
spdx-expression-parse "^3.0.0"
spdx-expression-parse "^3.0.0"
value-equal@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/value-equal/-/value-equal-1.0.1.tgz#1e0b794c734c5c0cade179c437d356d931a34d6c"
integrity sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw==
vendors@^1.0.0:
vendors@^1.0.0:
version "1.0.4"
version "1.0.4"
resolved "https://registry.yarnpkg.com/vendors/-/vendors-1.0.4.tgz#e2b800a53e7a29b93506c3cf41100d16c4c4ad8e"
resolved "https://registry.yarnpkg.com/vendors/-/vendors-1.0.4.tgz#e2b800a53e7a29b93506c3cf41100d16c4c4ad8e"
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录