Merge pull request #857 from cdr/web
[v2] Rewrite code-server to use new web stuff
|
@ -1,9 +1,10 @@
|
||||||
Dockerfile
|
Dockerfile
|
||||||
# Docs
|
build
|
||||||
doc/
|
deployment
|
||||||
# GitHub stuff
|
doc
|
||||||
.github
|
.github
|
||||||
.gitignore
|
.gitignore
|
||||||
|
.node-version
|
||||||
.travis.yml
|
.travis.yml
|
||||||
LICENSE
|
LICENSE
|
||||||
README.md
|
README.md
|
||||||
|
|
|
@ -1,8 +1,3 @@
|
||||||
/lib
|
|
||||||
node_modules
|
node_modules
|
||||||
dist
|
build
|
||||||
out
|
|
||||||
.DS_Store
|
|
||||||
release
|
release
|
||||||
.vscode
|
|
||||||
.cache
|
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
10.15.1
|
10.16.0
|
||||||
|
|
15
.travis.yml
|
@ -1,6 +1,6 @@
|
||||||
language: node_js
|
language: node_js
|
||||||
node_js:
|
node_js:
|
||||||
- 10.15.1
|
- 10.16.0
|
||||||
services:
|
services:
|
||||||
- docker
|
- docker
|
||||||
matrix:
|
matrix:
|
||||||
|
@ -8,20 +8,19 @@ matrix:
|
||||||
- os: linux
|
- os: linux
|
||||||
dist: trusty
|
dist: trusty
|
||||||
env:
|
env:
|
||||||
- VSCODE_VERSION="1.33.1" MAJOR_VERSION="1" VERSION="$MAJOR_VERSION.$TRAVIS_BUILD_NUMBER-vsc$VSCODE_VERSION" TARGET="centos"
|
- VSCODE_VERSION="e8fc7db0d1e3f3a94b1cdcc136d146134b7a4c9a" MAJOR_VERSION="2" VERSION="$MAJOR_VERSION.$TRAVIS_BUILD_NUMBER" TARGET="linux"
|
||||||
- os: linux
|
- os: linux
|
||||||
dist: trusty
|
dist: trusty
|
||||||
env:
|
env:
|
||||||
- VSCODE_VERSION="1.33.1" MAJOR_VERSION="1" VERSION="$MAJOR_VERSION.$TRAVIS_BUILD_NUMBER-vsc$VSCODE_VERSION" TARGET="alpine"
|
- VSCODE_VERSION="e8fc7db0d1e3f3a94b1cdcc136d146134b7a4c9a" MAJOR_VERSION="2" VERSION="$MAJOR_VERSION.$TRAVIS_BUILD_NUMBER" TARGET="alpine"
|
||||||
- os: osx
|
- os: osx
|
||||||
env:
|
env:
|
||||||
- VSCODE_VERSION="1.33.1" MAJOR_VERSION="1" VERSION="$MAJOR_VERSION.$TRAVIS_BUILD_NUMBER-vsc$VSCODE_VERSION"
|
- VSCODE_VERSION="e8fc7db0d1e3f3a94b1cdcc136d146134b7a4c9a" MAJOR_VERSION="2" VERSION="$MAJOR_VERSION.$TRAVIS_BUILD_NUMBER"
|
||||||
before_install:
|
before_install:
|
||||||
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get install libxkbfile-dev
|
- if [[ "$TRAVIS_BRANCH" == "master" ]]; then export MINIFY="true"; fi
|
||||||
libsecret-1-dev; fi
|
- if [[ "$TRAVIS_BRANCH" == "master" ]]; then export PACKAGE="true"; fi
|
||||||
- npm install -g yarn@1.12.3
|
|
||||||
script:
|
script:
|
||||||
- scripts/build.sh
|
- scripts/ci.bash
|
||||||
before_deploy:
|
before_deploy:
|
||||||
- echo "$VERSION" "$TRAVIS_COMMIT"
|
- echo "$VERSION" "$TRAVIS_COMMIT"
|
||||||
- git config --local user.name "$USER_NAME"
|
- git config --local user.name "$USER_NAME"
|
||||||
|
|
26
Dockerfile
|
@ -1,4 +1,6 @@
|
||||||
FROM node:10.15.1
|
FROM node:10.16.0
|
||||||
|
ARG codeServerVersion=docker
|
||||||
|
ARG vscodeVersion
|
||||||
|
|
||||||
# Install VS Code's deps. These are the only two it seems we need.
|
# Install VS Code's deps. These are the only two it seems we need.
|
||||||
RUN apt-get update && apt-get install -y \
|
RUN apt-get update && apt-get install -y \
|
||||||
|
@ -11,9 +13,10 @@ RUN npm install -g yarn@1.13
|
||||||
WORKDIR /src
|
WORKDIR /src
|
||||||
COPY . .
|
COPY . .
|
||||||
|
|
||||||
# In the future, we can use https://github.com/yarnpkg/rfcs/pull/53 to make yarn use the node_modules
|
RUN yarn \
|
||||||
# directly which should be fast as it is slow because it populates its own cache every time.
|
&& MINIFY=true yarn build "${vscodeVersion}" "${codeServerVersion}" \
|
||||||
RUN yarn && NODE_ENV=production yarn task build:server:binary
|
&& yarn binary "${vscodeVersion}" "${codeServerVersion}" \
|
||||||
|
&& mv "/src/build/code-server${codeServerVersion}-vsc${vscodeVersion}-linux-x86_64-built/code-server${codeServerVersion}-vsc${vscodeVersion}-linux-x86_64" /src/build/code-server
|
||||||
|
|
||||||
# We deploy with ubuntu so that devs have a familiar environment.
|
# We deploy with ubuntu so that devs have a familiar environment.
|
||||||
FROM ubuntu:18.04
|
FROM ubuntu:18.04
|
||||||
|
@ -30,7 +33,7 @@ RUN apt-get update && apt-get install -y \
|
||||||
wget
|
wget
|
||||||
|
|
||||||
RUN locale-gen en_US.UTF-8
|
RUN locale-gen en_US.UTF-8
|
||||||
# We unfortunately cannot use update-locale because docker will not use the env variables
|
# We cannot use update-locale because docker will not use the env variables
|
||||||
# configured in /etc/default/locale so we need to set it manually.
|
# configured in /etc/default/locale so we need to set it manually.
|
||||||
ENV LC_ALL=en_US.UTF-8
|
ENV LC_ALL=en_US.UTF-8
|
||||||
|
|
||||||
|
@ -38,16 +41,17 @@ RUN adduser --gecos '' --disabled-password coder && \
|
||||||
echo "coder ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers.d/nopasswd
|
echo "coder ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers.d/nopasswd
|
||||||
|
|
||||||
USER coder
|
USER coder
|
||||||
# We create first instead of just using WORKDIR as when WORKDIR creates, the user is root.
|
# We create first instead of just using WORKDIR as when WORKDIR creates, the
|
||||||
|
# user is root.
|
||||||
RUN mkdir -p /home/coder/project
|
RUN mkdir -p /home/coder/project
|
||||||
|
|
||||||
WORKDIR /home/coder/project
|
WORKDIR /home/coder/project
|
||||||
|
|
||||||
# This assures we have a volume mounted even if the user forgot to do bind mount.
|
# This ensures we have a volume mounted even if the user forgot to do bind
|
||||||
# So that they do not lose their data if they delete the container.
|
# mount. So that they do not lose their data if they delete the container.
|
||||||
VOLUME [ "/home/coder/project" ]
|
VOLUME [ "/home/coder/project" ]
|
||||||
|
|
||||||
COPY --from=0 /src/packages/server/cli-linux-x64 /usr/local/bin/code-server
|
COPY --from=0 /src/build/code-server /usr/local/bin/code-server
|
||||||
EXPOSE 8443
|
EXPOSE 8080
|
||||||
|
|
||||||
ENTRYPOINT ["dumb-init", "code-server"]
|
ENTRYPOINT ["dumb-init", "code-server", "--host", "0.0.0.0"]
|
||||||
|
|
147
README.md
|
@ -1,92 +1,133 @@
|
||||||
# code-server [!["Open Issues"](https://img.shields.io/github/issues-raw/cdr/code-server.svg)](https://github.com/cdr/code-server/issues) [!["Latest Release"](https://img.shields.io/github/release/cdr/code-server.svg)](https://github.com/cdr/code-server/releases/latest) [![MIT license](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/cdr/code-server/blob/master/LICENSE) [![Discord](https://img.shields.io/discord/463752820026376202.svg?label=&logo=discord&logoColor=ffffff&color=7389D8&labelColor=6A7EC2)](https://discord.gg/zxSwN8Z)
|
# code-server · [![MIT license](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/cdr/code-server/blob/master/LICENSE) [!["Latest Release"](https://img.shields.io/github/release/cdr/code-server.svg)](https://github.com/cdr/code-server/releases/latest) [![Build Status](https://img.shields.io/travis/com/cdr/code-server/master)](https://github.com/cdr/code-server)
|
||||||
|
|
||||||
**code-server v2 is almost out!**
|
`code-server` is [VS Code](https://github.com/Microsoft/vscode) running on a
|
||||||
[Get the preview here](https://github.com/cdr/code-server/releases).
|
remote server, accessible through the browser.
|
||||||
(Linux builds only at the moment.)
|
|
||||||
|
|
||||||
`code-server` is [VS Code](https://github.com/Microsoft/vscode) running on a remote server, accessible through the browser.
|
|
||||||
|
|
||||||
Try it out:
|
Try it out:
|
||||||
```bash
|
```bash
|
||||||
docker run -it -p 127.0.0.1:8443:8443 -v "${HOME}/.local/share/code-server:/home/coder/.local/share/code-server" -v "${PWD}:/home/coder/project" codercom/code-server --allow-http --no-auth
|
docker run -it -p 127.0.0.1:8080:8080 -v "${HOME}/.local/share/code-server:/home/coder/.local/share/code-server" -v "$PWD:/home/coder/project" codercom/code-server
|
||||||
```
|
```
|
||||||
|
|
||||||
- Code on your Chromebook, tablet, and laptop with a consistent dev environment.
|
- **Consistent environment:** Code on your Chromebook, tablet, and laptop with a
|
||||||
- If you have a Windows or Mac workstation, more easily develop for Linux.
|
consistent dev environment. develop more easily for Linux if you have a
|
||||||
- Take advantage of large cloud servers to speed up tests, compilations, downloads, and more.
|
Windows or Mac, and pick up where you left off when switching workstations.
|
||||||
- Preserve battery life when you're on the go.
|
- **Server-powered:** Take advantage of large cloud servers to speed up tests,
|
||||||
- All intensive computation runs on your server.
|
compilations, downloads, and more. Preserve battery life when you're on the go
|
||||||
- You're no longer running excess instances of Chrome.
|
since all intensive computation runs on your server.
|
||||||
|
|
||||||
![Screenshot](/doc/assets/ide.png)
|
![Screenshot](/doc/assets/ide.gif)
|
||||||
|
|
||||||
## Getting Started
|
## Getting Started
|
||||||
|
|
||||||
[![Create a Droplet](./doc/assets/do-new-droplet-btn.svg)](https://marketplace.digitalocean.com/apps/code-server?action=deploy)
|
|
||||||
|
|
||||||
### Run over SSH
|
### Run over SSH
|
||||||
|
|
||||||
Use [sshcode](https://github.com/codercom/sshcode) for a simple setup.
|
Use [sshcode](https://github.com/codercom/sshcode) for a simple setup.
|
||||||
|
|
||||||
### Docker
|
### Docker
|
||||||
|
See the Docker one-liner mentioned above. Dockerfile is at [/Dockerfile](/Dockerfile).
|
||||||
|
|
||||||
See docker oneliner mentioned above. Dockerfile is at [/Dockerfile](/Dockerfile).
|
To debug Golang using the
|
||||||
|
[ms-vscode-go extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode.Go),
|
||||||
|
you need to add `--security-opt seccomp=unconfined` to your `docker run`
|
||||||
|
arguments when launching code-server with Docker. See
|
||||||
|
[#725](https://github.com/cdr/code-server/issues/725) for details.
|
||||||
|
|
||||||
### Binaries
|
### Binaries
|
||||||
|
1. [Download a binary](https://github.com/cdr/code-server/releases). (Linux and
|
||||||
|
OS X supported. Windows coming soon)
|
||||||
|
2. Unpack the downloaded file then run the binary.
|
||||||
|
3. In your browser navigate to `localhost:8080`.
|
||||||
|
|
||||||
1. [Download a binary](https://github.com/cdr/code-server/releases) (Linux and OS X supported. Windows coming soon)
|
- For self-hosting and other information see [doc/quickstart.md](doc/quickstart.md).
|
||||||
2. Start the binary with the project directory as the first argument
|
- For hosting on cloud platforms see [doc/deploy.md](doc/deploy.md).
|
||||||
|
|
||||||
```
|
### Build
|
||||||
code-server <initial directory to open>
|
- If you also plan on developing, set the `OUT` environment variable. Otherwise
|
||||||
```
|
it will build in this directory which will cause issues because `yarn watch`
|
||||||
> You will be prompted to enter the password shown in the CLI
|
will try to compile the build directory as well.
|
||||||
`code-server` should now be running at https://localhost:8443.
|
- For now `@coder/nbin` is a global dependency.
|
||||||
|
- Run `yarn build ${vscodeVersion} ${codeServerVersion}` in this directory (for
|
||||||
> code-server uses a self-signed SSL certificate that may prompt your browser to ask you some additional questions before you proceed. Please [read here](doc/self-hosted/index.md) for more information.
|
example: `yarn build 1.36.0 development`).
|
||||||
|
- If you target the same VS Code version our Travis builds do everything will
|
||||||
For detailed instructions and troubleshooting, see the [self-hosted quick start guide](doc/self-hosted/index.md).
|
work but if you target some other version it might not (we have to do some
|
||||||
|
patching to VS Code so different versions aren't always compatible).
|
||||||
Quickstart guides for [Google Cloud](doc/admin/install/google_cloud.md), [AWS](doc/admin/install/aws.md), and [DigitalOcean](doc/admin/install/digitalocean.md).
|
- You can run the built code with `node path/to/build/out/vs/server/main.js` or run
|
||||||
|
`yarn binary` with the same arguments in the previous step to package the
|
||||||
How to [secure your setup](/doc/security/ssl.md).
|
code into a single binary.
|
||||||
|
|
||||||
## Development
|
|
||||||
|
|
||||||
### Known Issues
|
|
||||||
|
|
||||||
|
## Known Issues
|
||||||
|
- Uploading .vsix files doesn't work.
|
||||||
- Creating custom VS Code extensions and debugging them doesn't work.
|
- Creating custom VS Code extensions and debugging them doesn't work.
|
||||||
- To debug Golang using [ms-vscode-go extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode.Go), you need to add `--security-opt seccomp=unconfined` to your `docker run` arguments when launching code-server with Docker. See [#725](https://github.com/cdr/code-server/issues/725) for details.
|
- Extension profiling and tips are currently disabled.
|
||||||
|
|
||||||
### Future
|
## Future
|
||||||
- **Stay up to date!** Get notified about new releases of code-server.
|
- **Stay up to date!** Get notified about new releases of code-server.
|
||||||
![Screenshot](/doc/assets/release.gif)
|
![Screenshot](/doc/assets/release.gif)
|
||||||
- Windows support.
|
- Windows support.
|
||||||
- Electron and Chrome OS applications to bridge the gap between local<->remote.
|
- Electron and Chrome OS applications to bridge the gap between local<->remote.
|
||||||
- Run VS Code unit tests against our builds to ensure features work as expected.
|
- Run VS Code unit tests against our builds to ensure features work as expected.
|
||||||
|
|
||||||
### Extensions
|
## Extensions
|
||||||
|
At the moment we can't use the official VS Code Marketplace. We've created a
|
||||||
At the moment we can't use the official VSCode Marketplace. We've created a custom extension marketplace focused around open-sourced extensions. However, if you have access to the `.vsix` file, you can manually install the extension.
|
custom extension marketplace focused around open-sourced extensions. However,
|
||||||
|
you can manually download the extension to your extensions directory. It's also
|
||||||
|
possible to set your own marketplace URLs by setting the `SERVICE_URL` and
|
||||||
|
`ITEM_URL` environment variables.
|
||||||
|
|
||||||
## Telemetry
|
## Telemetry
|
||||||
|
Use the `--disable-telemetry` flag to completely disable telemetry. We use the
|
||||||
Use the `--disable-telemetry` flag or set `DISABLE_TELEMETRY=true` to disable tracking ENTIRELY.
|
data collected to improve code-server.
|
||||||
|
|
||||||
We use data collected to improve code-server.
|
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
### Development
|
||||||
|
```shell
|
||||||
|
git clone https://github.com/microsoft/vscode
|
||||||
|
cd vscode
|
||||||
|
git checkout <see travis.yml for the VS Code version to use here>
|
||||||
|
git clone https://github.com/cdr/code-server src/vs/server
|
||||||
|
cd src/vs/server
|
||||||
|
yarn patch:apply
|
||||||
|
yarn
|
||||||
|
yarn watch
|
||||||
|
# Wait for the initial compilation to complete (it will say "Finished compilation").
|
||||||
|
# Run the next command in another shell.
|
||||||
|
yarn start
|
||||||
|
# Visit http://localhost:8080
|
||||||
|
```
|
||||||
|
|
||||||
Development guides are coming soon.
|
If you run into issues about a different version of Node being used, try running
|
||||||
|
`npm rebuild` in the VS Code directory and ignore the error at the end from
|
||||||
|
`vscode-ripgrep`.
|
||||||
|
|
||||||
|
### Upgrading VS Code
|
||||||
|
We patch VS Code to provide and fix some functionality. As the web portion of VS
|
||||||
|
Code matures, we'll be able to shrink and maybe even entirely eliminate our
|
||||||
|
patch. In the meantime, however, upgrading the VS Code version requires ensuring
|
||||||
|
that the patch still applies and has the intended effects.
|
||||||
|
|
||||||
|
To generate a new patch, **stage all the changes** you want to be included in
|
||||||
|
the patch in the VS Code source, then run `yarn patch:generate` in this
|
||||||
|
directory.
|
||||||
|
|
||||||
|
Our changes include:
|
||||||
|
- Change the remote schema to `code-server`.
|
||||||
|
- Allow multiple extension directories (both user and built-in).
|
||||||
|
- Modify the loader, websocket, webview, service worker, and asset requests to
|
||||||
|
use the URL of the page as a base (and TLS if necessary for the websocket).
|
||||||
|
- Send client-side telemetry through the server and get the initial log level
|
||||||
|
from the server.
|
||||||
|
- Add an upload service for use in editor windows and the explorer along with a
|
||||||
|
file prefix to ignore for temporary files created during upload.
|
||||||
|
- Make changing the display language work.
|
||||||
|
- Make hiding or toggling the menu bar possible.
|
||||||
|
- Make it possible for us to load code on the client.
|
||||||
|
- Modify the build process to include our code.
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
[MIT](LICENSE)
|
[MIT](LICENSE)
|
||||||
|
|
||||||
## Enterprise
|
## Enterprise
|
||||||
|
Visit [our enterprise page](https://coder.com/enterprise) for more information
|
||||||
Visit [our website](https://coder.com/) for more information about our enterprise offering.
|
about our enterprise offering.
|
||||||
|
|
||||||
## Commercialization
|
## Commercialization
|
||||||
|
If you would like to commercialize code-server, please contact
|
||||||
If you would like to commercialize code-server, please contact contact@coder.com.
|
contact@coder.com.
|
||||||
|
|
|
@ -1,42 +0,0 @@
|
||||||
/**
|
|
||||||
* Script that detects platform name and arch.
|
|
||||||
* Cannot use os.platform() as that won't detect libc version
|
|
||||||
*/
|
|
||||||
import * as cp from "child_process";
|
|
||||||
import * as fs from "fs";
|
|
||||||
import * as os from "os";
|
|
||||||
|
|
||||||
enum Lib {
|
|
||||||
GLIBC,
|
|
||||||
MUSL,
|
|
||||||
}
|
|
||||||
|
|
||||||
const CLIB: Lib | undefined = ((): Lib | undefined => {
|
|
||||||
if (os.platform() !== "linux") {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const glibc = cp.spawnSync("getconf", ["GNU_LIBC_VERSION"]);
|
|
||||||
if (glibc.status === 0) {
|
|
||||||
return Lib.GLIBC;
|
|
||||||
}
|
|
||||||
|
|
||||||
const ldd = cp.spawnSync("ldd", ["--version"]);
|
|
||||||
if (ldd.stdout && ldd.stdout.indexOf("musl") !== -1) {
|
|
||||||
return Lib.MUSL;
|
|
||||||
}
|
|
||||||
|
|
||||||
const muslFile = fs.readdirSync("/lib").find((value) => value.startsWith("libc.musl"));
|
|
||||||
if (muslFile) {
|
|
||||||
return Lib.MUSL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Lib.GLIBC;
|
|
||||||
})();
|
|
||||||
|
|
||||||
export const platform = (): NodeJS.Platform | "musl" => {
|
|
||||||
if (CLIB === Lib.MUSL) {
|
|
||||||
return "musl";
|
|
||||||
}
|
|
||||||
|
|
||||||
return os.platform();
|
|
||||||
};
|
|
211
build/tasks.ts
|
@ -1,211 +0,0 @@
|
||||||
import { register, run } from "@coder/runner";
|
|
||||||
import { logger, field } from "@coder/logger";
|
|
||||||
import * as fs from "fs";
|
|
||||||
import * as fse from "fs-extra";
|
|
||||||
import * as os from "os";
|
|
||||||
import { platform } from "./platform";
|
|
||||||
import * as path from "path";
|
|
||||||
import * as zlib from "zlib";
|
|
||||||
import * as https from "https";
|
|
||||||
import * as tar from "tar";
|
|
||||||
|
|
||||||
const isWin = os.platform() === "win32";
|
|
||||||
const libPath = path.join(__dirname, "../lib");
|
|
||||||
const vscodePath = path.join(libPath, "vscode");
|
|
||||||
const defaultExtensionsPath = path.join(libPath, "extensions");
|
|
||||||
const pkgsPath = path.join(__dirname, "../packages");
|
|
||||||
const vscodeVersion = process.env.VSCODE_VERSION || "1.33.1";
|
|
||||||
const vsSourceUrl = `https://codesrv-ci.cdr.sh/vstar-${vscodeVersion}.tar.gz`;
|
|
||||||
|
|
||||||
const buildServerBinary = register("build:server:binary", async (runner) => {
|
|
||||||
logger.info("Building with environment", field("env", {
|
|
||||||
NODE_ENV: process.env.NODE_ENV,
|
|
||||||
VERSION: process.env.VERSION,
|
|
||||||
OSTYPE: process.env.OSTYPE,
|
|
||||||
TARGET: process.env.TARGET,
|
|
||||||
}));
|
|
||||||
|
|
||||||
await ensureInstalled();
|
|
||||||
await Promise.all([
|
|
||||||
buildBootstrapFork(),
|
|
||||||
buildWeb(),
|
|
||||||
buildServerBundle(),
|
|
||||||
buildAppBrowser(),
|
|
||||||
]);
|
|
||||||
|
|
||||||
await buildServerBinaryPackage();
|
|
||||||
});
|
|
||||||
|
|
||||||
const buildServerBinaryPackage = register("build:server:binary:package", async (runner) => {
|
|
||||||
const cliPath = path.join(pkgsPath, "server");
|
|
||||||
runner.cwd = cliPath;
|
|
||||||
if (!fs.existsSync(path.join(cliPath, "out"))) {
|
|
||||||
throw new Error("Cannot build binary without server bundle built");
|
|
||||||
}
|
|
||||||
await buildServerBinaryCopy();
|
|
||||||
const resp = await runner.execute(isWin ? "npm.cmd" : "npm", ["run", "build:binary"]);
|
|
||||||
if (resp.exitCode !== 0) {
|
|
||||||
throw new Error(`Failed to package binary: ${resp.stderr}`);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const buildServerBinaryCopy = register("build:server:binary:copy", async (runner) => {
|
|
||||||
const cliPath = path.join(pkgsPath, "server");
|
|
||||||
const cliBuildPath = path.join(cliPath, "build");
|
|
||||||
fse.removeSync(cliBuildPath);
|
|
||||||
fse.mkdirpSync(path.join(cliBuildPath, "extensions"));
|
|
||||||
const bootstrapForkPath = path.join(pkgsPath, "vscode", "out", "bootstrap-fork.js");
|
|
||||||
const webOutputPath = path.join(pkgsPath, "web", "out");
|
|
||||||
const browserAppOutputPath = path.join(pkgsPath, "app", "browser", "out");
|
|
||||||
let ripgrepPath = path.join(pkgsPath, "..", "lib", "vscode", "node_modules", "vscode-ripgrep", "bin", "rg");
|
|
||||||
if (isWin) {
|
|
||||||
ripgrepPath += ".exe";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!fs.existsSync(webOutputPath)) {
|
|
||||||
throw new Error("Web bundle must be built");
|
|
||||||
}
|
|
||||||
if (!fs.existsSync(defaultExtensionsPath)) {
|
|
||||||
throw new Error("Default extensions must be built");
|
|
||||||
}
|
|
||||||
if (!fs.existsSync(bootstrapForkPath)) {
|
|
||||||
throw new Error("Bootstrap fork must exist");
|
|
||||||
}
|
|
||||||
if (!fs.existsSync(ripgrepPath)) {
|
|
||||||
throw new Error("Ripgrep must exist");
|
|
||||||
}
|
|
||||||
fse.copySync(defaultExtensionsPath, path.join(cliBuildPath, "extensions"));
|
|
||||||
fs.writeFileSync(path.join(cliBuildPath, "bootstrap-fork.js.gz"), zlib.gzipSync(fs.readFileSync(bootstrapForkPath)));
|
|
||||||
const cpDir = (dir: string, rootPath: string, subdir?: "login"): void => {
|
|
||||||
const stat = fs.statSync(dir);
|
|
||||||
if (stat.isDirectory()) {
|
|
||||||
const paths = fs.readdirSync(dir);
|
|
||||||
paths.forEach((p) => cpDir(path.join(dir, p), rootPath, subdir));
|
|
||||||
} else if (stat.isFile()) {
|
|
||||||
const newPath = path.join(cliBuildPath, "web", subdir || "", path.relative(rootPath, dir));
|
|
||||||
fse.mkdirpSync(path.dirname(newPath));
|
|
||||||
fs.writeFileSync(newPath + ".gz", zlib.gzipSync(fs.readFileSync(dir)));
|
|
||||||
} else {
|
|
||||||
// Nothing
|
|
||||||
}
|
|
||||||
};
|
|
||||||
cpDir(webOutputPath, webOutputPath);
|
|
||||||
cpDir(browserAppOutputPath, browserAppOutputPath, "login");
|
|
||||||
fse.mkdirpSync(path.join(cliBuildPath, "dependencies"));
|
|
||||||
fse.copySync(ripgrepPath, path.join(cliBuildPath, "dependencies", "rg"));
|
|
||||||
});
|
|
||||||
|
|
||||||
const buildServerBundle = register("build:server:bundle", async (runner) => {
|
|
||||||
const cliPath = path.join(pkgsPath, "server");
|
|
||||||
runner.cwd = cliPath;
|
|
||||||
await runner.execute(isWin ? "npm.cmd" : "npm", ["run", "build"]);
|
|
||||||
});
|
|
||||||
|
|
||||||
const buildBootstrapFork = register("build:bootstrap-fork", async (runner) => {
|
|
||||||
await ensureInstalled();
|
|
||||||
await ensurePatched();
|
|
||||||
|
|
||||||
const vscodePkgPath = path.join(pkgsPath, "vscode");
|
|
||||||
runner.cwd = vscodePkgPath;
|
|
||||||
await runner.execute(isWin ? "npm.cmd" : "npm", ["run", "build:bootstrap-fork"]);
|
|
||||||
});
|
|
||||||
|
|
||||||
const buildAppBrowser = register("build:app:browser", async (runner) => {
|
|
||||||
await ensureInstalled();
|
|
||||||
|
|
||||||
const appPath = path.join(pkgsPath, "app/browser");
|
|
||||||
runner.cwd = appPath;
|
|
||||||
fse.removeSync(path.join(appPath, "out"));
|
|
||||||
await runner.execute(isWin ? "npm.cmd" : "npm", ["run", "build"]);
|
|
||||||
});
|
|
||||||
|
|
||||||
const buildWeb = register("build:web", async (runner) => {
|
|
||||||
await ensureInstalled();
|
|
||||||
await ensurePatched();
|
|
||||||
|
|
||||||
const webPath = path.join(pkgsPath, "web");
|
|
||||||
runner.cwd = webPath;
|
|
||||||
fse.removeSync(path.join(webPath, "out"));
|
|
||||||
await runner.execute(isWin ? "npm.cmd" : "npm", ["run", "build"]);
|
|
||||||
});
|
|
||||||
|
|
||||||
const ensureInstalled = register("vscode:install", async (runner) => {
|
|
||||||
runner.cwd = libPath;
|
|
||||||
|
|
||||||
if (fs.existsSync(vscodePath) && fs.existsSync(defaultExtensionsPath)) {
|
|
||||||
const pkgVersion = JSON.parse(fs.readFileSync(path.join(vscodePath, "package.json")).toString("utf8")).version;
|
|
||||||
if (pkgVersion === vscodeVersion) {
|
|
||||||
runner.cwd = vscodePath;
|
|
||||||
|
|
||||||
const reset = await runner.execute("git", ["reset", "--hard"]);
|
|
||||||
if (reset.exitCode !== 0) {
|
|
||||||
throw new Error(`Failed to clean git repository: ${reset.stderr}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fse.removeSync(libPath);
|
|
||||||
fse.mkdirpSync(libPath);
|
|
||||||
|
|
||||||
await new Promise<void>((resolve, reject): void => {
|
|
||||||
https.get(vsSourceUrl, (res) => {
|
|
||||||
if (res.statusCode !== 200) {
|
|
||||||
return reject(res.statusMessage);
|
|
||||||
}
|
|
||||||
|
|
||||||
res.pipe(tar.x({
|
|
||||||
C: libPath,
|
|
||||||
}).on("finish", () => {
|
|
||||||
resolve();
|
|
||||||
}).on("error", (err: Error) => {
|
|
||||||
reject(err);
|
|
||||||
}));
|
|
||||||
}).on("error", (err) => {
|
|
||||||
reject(err);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
const ensurePatched = register("vscode:patch", async (runner) => {
|
|
||||||
if (!fs.existsSync(vscodePath)) {
|
|
||||||
throw new Error("vscode must be cloned to patch");
|
|
||||||
}
|
|
||||||
await ensureInstalled();
|
|
||||||
|
|
||||||
runner.cwd = vscodePath;
|
|
||||||
const patchPath = path.join(__dirname, "../scripts/vscode.patch");
|
|
||||||
const apply = await runner.execute("git", ["apply", "--unidiff-zero", patchPath]);
|
|
||||||
if (apply.exitCode !== 0) {
|
|
||||||
throw new Error(`Failed to apply patches: ${apply.stderr}`);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
register("package", async (runner, releaseTag) => {
|
|
||||||
if (!releaseTag) {
|
|
||||||
throw new Error("Please specify the release tag.");
|
|
||||||
}
|
|
||||||
|
|
||||||
const releasePath = path.resolve(__dirname, "../release");
|
|
||||||
|
|
||||||
const archiveName = `code-server${releaseTag}-${platform()}-${os.arch()}`;
|
|
||||||
const archiveDir = path.join(releasePath, archiveName);
|
|
||||||
fse.removeSync(archiveDir);
|
|
||||||
fse.mkdirpSync(archiveDir);
|
|
||||||
|
|
||||||
const binaryPath = path.join(__dirname, `../packages/server/cli-${platform()}-${os.arch()}`);
|
|
||||||
const binaryDestination = path.join(archiveDir, "code-server");
|
|
||||||
fse.copySync(binaryPath, binaryDestination);
|
|
||||||
fs.chmodSync(binaryDestination, "755");
|
|
||||||
["README.md", "LICENSE"].forEach((fileName) => {
|
|
||||||
fse.copySync(path.resolve(__dirname, `../${fileName}`), path.join(archiveDir, fileName));
|
|
||||||
});
|
|
||||||
|
|
||||||
runner.cwd = releasePath;
|
|
||||||
await (os.platform() === "linux"
|
|
||||||
? runner.execute("tar", ["-cvzf", `${archiveName}.tar.gz`, `${archiveName}`])
|
|
||||||
: runner.execute("zip", ["-r", `${archiveName}.zip`, `${archiveName}`]));
|
|
||||||
});
|
|
||||||
|
|
||||||
run();
|
|
|
@ -1,5 +0,0 @@
|
||||||
apiVersion: v1
|
|
||||||
appVersion: "1.0"
|
|
||||||
description: A Helm chart for code-server
|
|
||||||
name: code-server
|
|
||||||
version: 1.0.0
|
|
|
@ -1,115 +0,0 @@
|
||||||
# code-server
|
|
||||||
|
|
||||||
[code-server](https://github.com/cdr/code-server) code-server is VS Code running
|
|
||||||
on a remote server, accessible through the browser.
|
|
||||||
|
|
||||||
## TL;DR;
|
|
||||||
|
|
||||||
```console
|
|
||||||
$ git clone https://github.com/cdr/code-server.git
|
|
||||||
$ helm install deployment/chart
|
|
||||||
```
|
|
||||||
|
|
||||||
## Introduction
|
|
||||||
|
|
||||||
This chart bootstraps a code-server deployment on a
|
|
||||||
[Kubernetes](http://kubernetes.io) cluster using the [Helm](https://helm.sh)
|
|
||||||
package manager.
|
|
||||||
|
|
||||||
## Prerequisites
|
|
||||||
|
|
||||||
- Kubernetes 1.6+
|
|
||||||
|
|
||||||
## Installing the Chart
|
|
||||||
|
|
||||||
To install the chart with the release name `my-release`:
|
|
||||||
|
|
||||||
```console
|
|
||||||
$ helm install --name my-release deployment/chart
|
|
||||||
```
|
|
||||||
|
|
||||||
The command deploys code-server on the Kubernetes cluster in the default
|
|
||||||
configuration. The [configuration](#configuration) section lists the parameters
|
|
||||||
that can be configured during installation.
|
|
||||||
|
|
||||||
> **Tip**: List all releases using `helm list`
|
|
||||||
|
|
||||||
## Uninstalling the Chart
|
|
||||||
|
|
||||||
To uninstall/delete the `my-release` deployment:
|
|
||||||
|
|
||||||
```console
|
|
||||||
$ helm delete my-release
|
|
||||||
```
|
|
||||||
|
|
||||||
The command removes all the Kubernetes components associated with the chart and
|
|
||||||
deletes the release.
|
|
||||||
|
|
||||||
## Configuration
|
|
||||||
|
|
||||||
The following table lists the configurable parameters of the nginx-ingress chart
|
|
||||||
and their default values.
|
|
||||||
|
|
||||||
|
|
||||||
The following table lists the configurable parameters of the code-server chart
|
|
||||||
and their default values.
|
|
||||||
|
|
||||||
| Parameter | Description | Default |
|
|
||||||
| --------------------------------- | ------------------------------------------ | --------------------------------------------------------- |
|
|
||||||
| `image.registry` | Code-server image registry | `docker.io` |
|
|
||||||
| `image.repository` | Code-server Image name | `codercom/code-server` |
|
|
||||||
| `image.tag` | Code-server Image tag | `{TAG_NAME}` |
|
|
||||||
| `image.pullPolicy` | Code-server image pull policy | `IfNotPresent` |
|
|
||||||
| `nameOverride` | String to partially override code-server.fullname template with a string (will prepend the release name) | `nil` |
|
|
||||||
| `fullnameOverride` | String to fully override code-server.fullname template with a string |
|
|
||||||
| `hostnameOverride` | String to fully override code-server container hostname |
|
|
||||||
| `service.type` | Kubernetes Service type | `NodePort` |
|
|
||||||
| `service.port` | Service HTTP port | `8443` |
|
|
||||||
| `ingress.enabled` | Enable ingress controller resource | `false` |
|
|
||||||
| `ingress.hosts[0].name` | Hostname to your code-server installation | `code-server.local` |
|
|
||||||
| `ingress.hosts[0].path` | Path within the url structure | `/` |
|
|
||||||
| `ingress.hosts[0].tls` | Utilize TLS backend in ingress | `false` |
|
|
||||||
| `ingress.hosts[0].certManager` | Add annotations for cert-manager | `false` |
|
|
||||||
| `ingress.hosts[0].tlsSecret` | TLS Secret (certificates) | `code-server.local-tls-secret` |
|
|
||||||
| `ingress.hosts[0].annotations` | Annotations for this host's ingress record | `[]` |
|
|
||||||
| `ingress.secrets[0].name` | TLS Secret Name | `nil` |
|
|
||||||
| `ingress.secrets[0].certificate` | TLS Secret Certificate | `nil` |
|
|
||||||
| `ingress.secrets[0].key` | TLS Secret Key | `nil` |
|
|
||||||
| `extraArgs` | Additional code-server container arguments | `{}` |
|
|
||||||
| `extraVars` | Optional environment variables for code-server | `{}` |
|
|
||||||
| `volumePermissions.enabled` | Enable volume permissions init container | `true` |
|
|
||||||
| `volumePermissions.securityContext.runAsUser` | User ID for the init container | `0` |
|
|
||||||
| `securityContext.enabled` | Enable security context | `true` |
|
|
||||||
| `securityContext.fsGroup` | Group ID for the container | `1000` |
|
|
||||||
| `securityContext.runAsUser` | User ID for the container | `1000` |
|
|
||||||
| `resources` | CPU/Memory resource requests/limits | `{}` |
|
|
||||||
| `persistence.enabled` | Enable persistence using PVC | `true` |
|
|
||||||
| `persistence.storageClass` | PVC Storage Class for code-server volume | `nil` |
|
|
||||||
| `persistence.accessMode` | PVC Access Mode for code-server volume | `ReadWriteOnce` |
|
|
||||||
| `persistence.size` | PVC Storage Request for code-server volume | `8Gi` |
|
|
||||||
| `extraContainers` | Sidecar containers to add to the code-server pod | `{}` |
|
|
||||||
| `extraSecretMounts` | Additional code-server server secret mounts | `[]` |
|
|
||||||
| `extraVolumeMounts` | Additional code-server server volume mounts | `[]` |
|
|
||||||
| `extraConfigmapMounts` | Additional code-server server configMap volume mounts | `[]` |
|
|
||||||
|
|
||||||
Specify each parameter using the `--set key=value[,key=value]` argument to `helm
|
|
||||||
install`. For example,
|
|
||||||
|
|
||||||
```console
|
|
||||||
$ helm install --name my-release \
|
|
||||||
--set persistence.enabled=false \
|
|
||||||
deployment/chart
|
|
||||||
```
|
|
||||||
|
|
||||||
The above command sets the the persistence storage to false.
|
|
||||||
|
|
||||||
Alternatively, a YAML file that specifies the values for the above parameters
|
|
||||||
can be provided while installing the chart. For example,
|
|
||||||
|
|
||||||
```console
|
|
||||||
$ helm install --name my-release -f values.yaml deployment/chart
|
|
||||||
```
|
|
||||||
|
|
||||||
> **Tip**: You can use the default [values.yaml](values.yaml)
|
|
||||||
|
|
||||||
|
|
|
@ -1,25 +0,0 @@
|
||||||
1. Get the application URL by running these commands:
|
|
||||||
{{- if .Values.ingress.enabled }}
|
|
||||||
{{- range $host := .Values.ingress.hosts }}
|
|
||||||
{{- range .paths }}
|
|
||||||
http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ . }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
{{- else if contains "NodePort" .Values.service.type }}
|
|
||||||
export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "code-server.fullname" . }})
|
|
||||||
export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
|
|
||||||
echo http://$NODE_IP:$NODE_PORT
|
|
||||||
{{- else if contains "LoadBalancer" .Values.service.type }}
|
|
||||||
NOTE: It may take a few minutes for the LoadBalancer IP to be available.
|
|
||||||
You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "code-server.fullname" . }}'
|
|
||||||
export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "code-server.fullname" . }} -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
|
|
||||||
echo http://$SERVICE_IP:{{ .Values.service.port }}
|
|
||||||
{{- else if contains "ClusterIP" .Values.service.type }}
|
|
||||||
export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "code-server.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}")
|
|
||||||
echo "Visit http://127.0.0.1:8080 to use your application"
|
|
||||||
kubectl port-forward $POD_NAME 8080:80
|
|
||||||
{{- end }}
|
|
||||||
|
|
||||||
Administrator credentials:
|
|
||||||
|
|
||||||
Password : $(kubectl get secret --namespace {{ .Release.Namespace }} {{ template "code-server.fullname" . }} -o jsonpath="{.data.password}" | base64 --decode)
|
|
|
@ -1,43 +0,0 @@
|
||||||
{{/* vim: set filetype=mustache: */}}
|
|
||||||
{{/*
|
|
||||||
Expand the name of the chart.
|
|
||||||
*/}}
|
|
||||||
{{- define "code-server.name" -}}
|
|
||||||
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
|
|
||||||
{{- end -}}
|
|
||||||
|
|
||||||
{{/*
|
|
||||||
Create a default fully qualified app name.
|
|
||||||
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
|
|
||||||
If release name contains chart name it will be used as a full name.
|
|
||||||
*/}}
|
|
||||||
{{- define "code-server.fullname" -}}
|
|
||||||
{{- if .Values.fullnameOverride -}}
|
|
||||||
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}}
|
|
||||||
{{- else -}}
|
|
||||||
{{- $name := default .Chart.Name .Values.nameOverride -}}
|
|
||||||
{{- if contains $name .Release.Name -}}
|
|
||||||
{{- .Release.Name | trunc 63 | trimSuffix "-" -}}
|
|
||||||
{{- else -}}
|
|
||||||
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}}
|
|
||||||
{{- end -}}
|
|
||||||
{{- end -}}
|
|
||||||
{{- end -}}
|
|
||||||
|
|
||||||
{{/*
|
|
||||||
Create chart name and version as used by the chart label.
|
|
||||||
*/}}
|
|
||||||
{{- define "code-server.chart" -}}
|
|
||||||
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}}
|
|
||||||
{{- end -}}
|
|
||||||
|
|
||||||
{{/*
|
|
||||||
Create the name of the service account to use
|
|
||||||
*/}}
|
|
||||||
{{- define "code-server.serviceAccountName" -}}
|
|
||||||
{{- if .Values.serviceAccount.create -}}
|
|
||||||
{{ default (include "code-server.fullname" .) .Values.serviceAccount.name }}
|
|
||||||
{{- else -}}
|
|
||||||
{{ default "default" .Values.serviceAccount.name }}
|
|
||||||
{{- end -}}
|
|
||||||
{{- end -}}
|
|
|
@ -1,144 +0,0 @@
|
||||||
apiVersion: apps/v1
|
|
||||||
kind: Deployment
|
|
||||||
metadata:
|
|
||||||
name: {{ include "code-server.fullname" . }}
|
|
||||||
labels:
|
|
||||||
app.kubernetes.io/name: {{ include "code-server.name" . }}
|
|
||||||
helm.sh/chart: {{ include "code-server.chart" . }}
|
|
||||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
|
||||||
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
|
||||||
spec:
|
|
||||||
replicas: 1
|
|
||||||
strategy:
|
|
||||||
type: Recreate
|
|
||||||
selector:
|
|
||||||
matchLabels:
|
|
||||||
app.kubernetes.io/name: {{ include "code-server.name" . }}
|
|
||||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
|
||||||
template:
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
app.kubernetes.io/name: {{ include "code-server.name" . }}
|
|
||||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
|
||||||
spec:
|
|
||||||
{{- if .Values.hostnameOverride }}
|
|
||||||
hostname: {{ .Values.hostnameOverride }}
|
|
||||||
{{- end }}
|
|
||||||
{{- if .Values.securityContext.enabled }}
|
|
||||||
securityContext:
|
|
||||||
fsGroup: {{ .Values.securityContext.fsGroup }}
|
|
||||||
{{- end }}
|
|
||||||
{{- if and .Values.volumePermissions.enabled .Values.persistence.enabled }}
|
|
||||||
initContainers:
|
|
||||||
- name: init-chmod-data
|
|
||||||
image: busybox:latest
|
|
||||||
imagePullPolicy: IfNotPresent
|
|
||||||
command:
|
|
||||||
- sh
|
|
||||||
- -c
|
|
||||||
- |
|
|
||||||
chown -R {{ .Values.securityContext.runAsUser }}:{{ .Values.securityContext.fsGroup }} /home/coder
|
|
||||||
securityContext:
|
|
||||||
runAsUser: {{ .Values.volumePermissions.securityContext.runAsUser }}
|
|
||||||
volumeMounts:
|
|
||||||
- name: data
|
|
||||||
mountPath: /home/coder
|
|
||||||
{{- end }}
|
|
||||||
containers:
|
|
||||||
{{- if .Values.extraContainers }}
|
|
||||||
{{ toYaml .Values.extraContainers | indent 8}}
|
|
||||||
{{- end }}
|
|
||||||
- name: {{ .Chart.Name }}
|
|
||||||
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
|
|
||||||
imagePullPolicy: {{ .Values.image.pullPolicy }}
|
|
||||||
{{- if .Values.securityContext.enabled }}
|
|
||||||
securityContext:
|
|
||||||
runAsUser: {{ .Values.securityContext.runAsUser }}
|
|
||||||
{{- end }}
|
|
||||||
env:
|
|
||||||
{{- if .Values.extraVars }}
|
|
||||||
{{ toYaml .Values.extraVars | indent 10 }}
|
|
||||||
{{- end }}
|
|
||||||
- name: PASSWORD
|
|
||||||
valueFrom:
|
|
||||||
secretKeyRef:
|
|
||||||
{{- if .Values.existingSecret }}
|
|
||||||
name: {{ .Values.existingSecret }}
|
|
||||||
{{- else }}
|
|
||||||
name: {{ template "code-server.fullname" . }}
|
|
||||||
{{- end }}
|
|
||||||
key: password
|
|
||||||
{{- if .Values.extraArgs }}
|
|
||||||
args:
|
|
||||||
{{ toYaml .Values.extraArgs | indent 10 }}
|
|
||||||
{{- end }}
|
|
||||||
volumeMounts:
|
|
||||||
- name: data
|
|
||||||
mountPath: /home/coder/project
|
|
||||||
subPath: project
|
|
||||||
- name: data
|
|
||||||
mountPath: /home/coder/.local/share/code-server
|
|
||||||
subPath: code-server
|
|
||||||
{{- range .Values.extraConfigmapMounts }}
|
|
||||||
- name: {{ .name }}
|
|
||||||
mountPath: {{ .mountPath }}
|
|
||||||
subPath: {{ .subPath | default "" }}
|
|
||||||
readOnly: {{ .readOnly }}
|
|
||||||
{{- end }}
|
|
||||||
{{- range .Values.extraSecretMounts }}
|
|
||||||
- name: {{ .name }}
|
|
||||||
mountPath: {{ .mountPath }}
|
|
||||||
readOnly: {{ .readOnly }}
|
|
||||||
{{- end }}
|
|
||||||
{{- range .Values.extraVolumeMounts }}
|
|
||||||
- name: {{ .name }}
|
|
||||||
mountPath: {{ .mountPath }}
|
|
||||||
subPath: {{ .subPath | default "" }}
|
|
||||||
readOnly: {{ .readOnly }}
|
|
||||||
{{- end }}
|
|
||||||
ports:
|
|
||||||
- name: http
|
|
||||||
containerPort: 8443
|
|
||||||
protocol: TCP
|
|
||||||
livenessProbe:
|
|
||||||
httpGet:
|
|
||||||
path: /
|
|
||||||
port: http
|
|
||||||
readinessProbe:
|
|
||||||
httpGet:
|
|
||||||
path: /
|
|
||||||
port: http
|
|
||||||
resources:
|
|
||||||
{{- toYaml .Values.resources | nindent 12 }}
|
|
||||||
{{- with .Values.nodeSelector }}
|
|
||||||
nodeSelector:
|
|
||||||
{{- toYaml . | nindent 8 }}
|
|
||||||
{{- end }}
|
|
||||||
{{- with .Values.affinity }}
|
|
||||||
affinity:
|
|
||||||
{{- toYaml . | nindent 8 }}
|
|
||||||
{{- end }}
|
|
||||||
{{- with .Values.tolerations }}
|
|
||||||
tolerations:
|
|
||||||
{{- toYaml . | nindent 8 }}
|
|
||||||
{{- end }}
|
|
||||||
serviceAccountName: {{ template "code-server.serviceAccountName" . }}
|
|
||||||
volumes:
|
|
||||||
- name: data
|
|
||||||
{{- if .Values.persistence.enabled }}
|
|
||||||
persistentVolumeClaim:
|
|
||||||
claimName: {{ .Values.persistence.existingClaim | default (include "code-server.fullname" .) }}
|
|
||||||
{{- else }}
|
|
||||||
emptyDir: {}
|
|
||||||
{{- end -}}
|
|
||||||
{{- range .Values.extraSecretMounts }}
|
|
||||||
- name: {{ .name }}
|
|
||||||
secret:
|
|
||||||
secretName: {{ .secretName }}
|
|
||||||
defaultMode: {{ .defaultMode }}
|
|
||||||
{{- end }}
|
|
||||||
{{- range .Values.extraVolumeMounts }}
|
|
||||||
- name: {{ .name }}
|
|
||||||
persistentVolumeClaim:
|
|
||||||
claimName: {{ .existingClaim }}
|
|
||||||
{{- end }}
|
|
|
@ -1,39 +0,0 @@
|
||||||
{{- if .Values.ingress.enabled -}}
|
|
||||||
{{- $fullName := include "code-server.fullname" . -}}
|
|
||||||
apiVersion: extensions/v1beta1
|
|
||||||
kind: Ingress
|
|
||||||
metadata:
|
|
||||||
name: {{ $fullName }}
|
|
||||||
labels:
|
|
||||||
app.kubernetes.io/name: {{ include "code-server.name" . }}
|
|
||||||
helm.sh/chart: {{ include "code-server.chart" . }}
|
|
||||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
|
||||||
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
|
||||||
{{- with .Values.ingress.annotations }}
|
|
||||||
annotations:
|
|
||||||
{{- toYaml . | nindent 4 }}
|
|
||||||
{{- end }}
|
|
||||||
spec:
|
|
||||||
{{- if .Values.ingress.tls }}
|
|
||||||
tls:
|
|
||||||
{{- range .Values.ingress.tls }}
|
|
||||||
- hosts:
|
|
||||||
{{- range .hosts }}
|
|
||||||
- {{ . | quote }}
|
|
||||||
{{- end }}
|
|
||||||
secretName: {{ .secretName }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
rules:
|
|
||||||
{{- range .Values.ingress.hosts }}
|
|
||||||
- host: {{ .host | quote }}
|
|
||||||
http:
|
|
||||||
paths:
|
|
||||||
{{- range .paths }}
|
|
||||||
- path: {{ . }}
|
|
||||||
backend:
|
|
||||||
serviceName: {{ $fullName }}
|
|
||||||
servicePort: http
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
|
@ -1,29 +0,0 @@
|
||||||
{{- if and .Values.persistence.enabled (not .Values.persistence.existingClaim) }}
|
|
||||||
kind: PersistentVolumeClaim
|
|
||||||
apiVersion: v1
|
|
||||||
metadata:
|
|
||||||
name: {{ include "code-server.fullname" . }}
|
|
||||||
namespace: {{ .Release.Namespace }}
|
|
||||||
{{- with .Values.persistence.annotations }}
|
|
||||||
annotations:
|
|
||||||
{{ toYaml . | indent 4 }}
|
|
||||||
{{- end }}
|
|
||||||
labels:
|
|
||||||
app.kubernetes.io/name: {{ include "code-server.name" . }}
|
|
||||||
helm.sh/chart: {{ include "code-server.chart" . }}
|
|
||||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
|
||||||
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
|
||||||
spec:
|
|
||||||
accessModes:
|
|
||||||
- {{ .Values.persistence.accessMode | quote }}
|
|
||||||
resources:
|
|
||||||
requests:
|
|
||||||
storage: {{ .Values.persistence.size | quote }}
|
|
||||||
{{- if .Values.persistence.storageClass }}
|
|
||||||
{{- if (eq "-" .Values.persistence.storageClass) }}
|
|
||||||
storageClassName: ""
|
|
||||||
{{- else }}
|
|
||||||
storageClassName: "{{ .Values.persistence.storageClass }}"
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
|
@ -1,18 +0,0 @@
|
||||||
apiVersion: v1
|
|
||||||
kind: Secret
|
|
||||||
metadata:
|
|
||||||
name: {{ include "code-server.fullname" . }}
|
|
||||||
annotations:
|
|
||||||
"helm.sh/hook": "pre-install"
|
|
||||||
labels:
|
|
||||||
app.kubernetes.io/name: {{ include "code-server.name" . }}
|
|
||||||
helm.sh/chart: {{ include "code-server.chart" . }}
|
|
||||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
|
||||||
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
|
||||||
type: Opaque
|
|
||||||
data:
|
|
||||||
{{ if .Values.password }}
|
|
||||||
password: "{{ .Values.password | b64enc }}"
|
|
||||||
{{ else }}
|
|
||||||
password: "{{ randAlphaNum 24 | b64enc }}"
|
|
||||||
{{ end }}
|
|
|
@ -1,19 +0,0 @@
|
||||||
apiVersion: v1
|
|
||||||
kind: Service
|
|
||||||
metadata:
|
|
||||||
name: {{ include "code-server.fullname" . }}
|
|
||||||
labels:
|
|
||||||
app.kubernetes.io/name: {{ include "code-server.name" . }}
|
|
||||||
helm.sh/chart: {{ include "code-server.chart" . }}
|
|
||||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
|
||||||
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
|
||||||
spec:
|
|
||||||
type: {{ .Values.service.type }}
|
|
||||||
ports:
|
|
||||||
- port: {{ .Values.service.port }}
|
|
||||||
targetPort: http
|
|
||||||
protocol: TCP
|
|
||||||
name: http
|
|
||||||
selector:
|
|
||||||
app.kubernetes.io/name: {{ include "code-server.name" . }}
|
|
||||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
|
|
@ -1,11 +0,0 @@
|
||||||
{{- if or .Values.serviceAccount.create -}}
|
|
||||||
apiVersion: v1
|
|
||||||
kind: ServiceAccount
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
app.kubernetes.io/name: {{ include "code-server.name" . }}
|
|
||||||
helm.sh/chart: {{ include "code-server.chart" . }}
|
|
||||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
|
||||||
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
|
||||||
name: {{ template "code-server.serviceAccountName" . }}
|
|
||||||
{{- end -}}
|
|
|
@ -1,18 +0,0 @@
|
||||||
apiVersion: v1
|
|
||||||
kind: Pod
|
|
||||||
metadata:
|
|
||||||
name: "{{ include "code-server.fullname" . }}-test-connection"
|
|
||||||
labels:
|
|
||||||
app.kubernetes.io/name: {{ include "code-server.name" . }}
|
|
||||||
helm.sh/chart: {{ include "code-server.chart" . }}
|
|
||||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
|
||||||
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
|
||||||
annotations:
|
|
||||||
"helm.sh/hook": test-success
|
|
||||||
spec:
|
|
||||||
containers:
|
|
||||||
- name: wget
|
|
||||||
image: busybox
|
|
||||||
command: ['wget']
|
|
||||||
args: ['{{ include "code-server.fullname" . }}:{{ .Values.service.port }}']
|
|
||||||
restartPolicy: Never
|
|
|
@ -1,135 +0,0 @@
|
||||||
# Default values for code-server.
|
|
||||||
# This is a YAML-formatted file.
|
|
||||||
# Declare variables to be passed into your templates.
|
|
||||||
|
|
||||||
image:
|
|
||||||
repository: codercom/code-server
|
|
||||||
tag: 1.1156-vsc1.33.1
|
|
||||||
pullPolicy: Always
|
|
||||||
|
|
||||||
nameOverride: ""
|
|
||||||
fullnameOverride: ""
|
|
||||||
hostnameOverride: ""
|
|
||||||
|
|
||||||
service:
|
|
||||||
type: NodePort
|
|
||||||
port: 8443
|
|
||||||
|
|
||||||
ingress:
|
|
||||||
enabled: false
|
|
||||||
#annotations:
|
|
||||||
# kubernetes.io/ingress.class: nginx
|
|
||||||
# kubernetes.io/tls-acme: "true"
|
|
||||||
#hosts:
|
|
||||||
# - host: code-server.example.loc
|
|
||||||
# paths:
|
|
||||||
# - /
|
|
||||||
|
|
||||||
#tls:
|
|
||||||
# - secretName: code-server
|
|
||||||
# hosts:
|
|
||||||
# - code-server.example.loc
|
|
||||||
|
|
||||||
# Optional additional arguments
|
|
||||||
extraArgs: []
|
|
||||||
# - --allow-http
|
|
||||||
# - --no-auth
|
|
||||||
|
|
||||||
# Optional additional environment variables
|
|
||||||
extraVars: []
|
|
||||||
# - name: DISABLE_TELEMETRY
|
|
||||||
# value: true
|
|
||||||
|
|
||||||
##
|
|
||||||
## Init containers parameters:
|
|
||||||
## volumePermissions: Change the owner of the persist volume mountpoint to RunAsUser:fsGroup
|
|
||||||
##
|
|
||||||
volumePermissions:
|
|
||||||
enabled: true
|
|
||||||
securityContext:
|
|
||||||
runAsUser: 0
|
|
||||||
|
|
||||||
## Pod Security Context
|
|
||||||
## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/
|
|
||||||
##
|
|
||||||
securityContext:
|
|
||||||
enabled: true
|
|
||||||
fsGroup: 1000
|
|
||||||
runAsUser: 1000
|
|
||||||
|
|
||||||
resources: {}
|
|
||||||
# We usually recommend not to specify default resources and to leave this as a conscious
|
|
||||||
# choice for the user. This also increases chances charts run on environments with little
|
|
||||||
# resources, such as Minikube. If you do want to specify resources, uncomment the following
|
|
||||||
# lines, adjust them as necessary, and remove the curly braces after 'resources:'.
|
|
||||||
# limits:
|
|
||||||
# cpu: 100m
|
|
||||||
# memory: 128Mi
|
|
||||||
# requests:
|
|
||||||
# cpu: 100m
|
|
||||||
# memory: 1000Mi
|
|
||||||
|
|
||||||
nodeSelector: {}
|
|
||||||
|
|
||||||
tolerations: []
|
|
||||||
|
|
||||||
affinity: {}
|
|
||||||
|
|
||||||
## Persist data to a persistent volume
|
|
||||||
persistence:
|
|
||||||
enabled: true
|
|
||||||
## code-server data Persistent Volume Storage Class
|
|
||||||
## If defined, storageClassName: <storageClass>
|
|
||||||
## If set to "-", storageClassName: "", which disables dynamic provisioning
|
|
||||||
## If undefined (the default) or set to null, no storageClassName spec is
|
|
||||||
## set, choosing the default provisioner. (gp2 on AWS, standard on
|
|
||||||
## GKE, AWS & OpenStack)
|
|
||||||
##
|
|
||||||
# storageClass: "-"
|
|
||||||
accessMode: ReadWriteOnce
|
|
||||||
size: 1Gi
|
|
||||||
annotations: {}
|
|
||||||
|
|
||||||
serviceAccount:
|
|
||||||
create: true
|
|
||||||
name:
|
|
||||||
|
|
||||||
## Enable an Specify container in extraContainers.
|
|
||||||
## This is meant to allow adding code-server dependencies, like docker-dind.
|
|
||||||
extraContainers: |
|
|
||||||
#- name: docker-dind
|
|
||||||
# image: docker:19.03-dind
|
|
||||||
# imagePullPolicy: IfNotPresent
|
|
||||||
# resources:
|
|
||||||
# requests:
|
|
||||||
# cpu: 250m
|
|
||||||
# memory: 256M
|
|
||||||
# securityContext:
|
|
||||||
# privileged: true
|
|
||||||
# procMount: Default
|
|
||||||
# env:
|
|
||||||
# - name: DOCKER_TLS_CERTDIR
|
|
||||||
# value: ""
|
|
||||||
# - name: DOCKER_DRIVER
|
|
||||||
# value: "overlay2"
|
|
||||||
|
|
||||||
## Additional code-server secret mounts
|
|
||||||
extraSecretMounts: []
|
|
||||||
# - name: secret-files
|
|
||||||
# mountPath: /etc/secrets
|
|
||||||
# secretName: code-server-secret-files
|
|
||||||
# readOnly: true
|
|
||||||
|
|
||||||
## Additional code-server volume mounts
|
|
||||||
extraVolumeMounts: []
|
|
||||||
# - name: extra-volume
|
|
||||||
# mountPath: /mnt/volume
|
|
||||||
# readOnly: true
|
|
||||||
# existingClaim: volume-claim
|
|
||||||
|
|
||||||
extraConfigmapMounts: []
|
|
||||||
# - name: certs-configmap
|
|
||||||
# mountPath: /etc/code-server/ssl/
|
|
||||||
# subPath: certificates.crt # (optional)
|
|
||||||
# configMap: certs-configmap
|
|
||||||
# readOnly: true
|
|
|
@ -1,116 +0,0 @@
|
||||||
# Deploy on AWS EC2
|
|
||||||
|
|
||||||
This tutorial shows you how to deploy `code-server` on an AWS EC2 instance.
|
|
||||||
|
|
||||||
If you're just starting out, we recommend
|
|
||||||
[installing code-server locally](self-hosted-docs). It takes only a few minutes
|
|
||||||
and lets you try out all of the features locally.
|
|
||||||
|
|
||||||
If you get stuck or need help at anytime, [file an issue](create-issue),
|
|
||||||
[tweet (@coderhq)](twitter-coderhq) or [email](email-coder).
|
|
||||||
|
|
||||||
[self-hosted-docs]: ../../self-hosted/index.md
|
|
||||||
[create-issue]: https://github.com/cdr/code-server/issues/new?title=Improve+AWS+quickstart+guide
|
|
||||||
[twitter-coderhq]: https://twitter.com/coderhq
|
|
||||||
[email-coder]: mailto:support@coder.com?subject=AWS%20quickstart%20guide
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Creating an Instance using the AWS Launch Wizard
|
|
||||||
|
|
||||||
1. Click **Launch Instance** from your [EC2 dashboard](ec2-home).
|
|
||||||
2. Select the "Ubuntu Server 18.04 LTS (HVM), SSD Volume Type" AMI..
|
|
||||||
3. Select an appropriate instance size (we recommend t2.medium/large, depending
|
|
||||||
on team size and number of repositories/languages enabled), then **Next:
|
|
||||||
Configure Instance Details**.
|
|
||||||
4. Select **Next: ...** until you get to the **Configure Security Group** page,
|
|
||||||
then add a **Custom TCP Rule** rule with port range set to `8443` and source
|
|
||||||
set to "Anywhere".
|
|
||||||
> Rules with source of 0.0.0.0/0 allow all IP addresses to access your
|
|
||||||
> instance. We recommend setting [security group rules](ec2-sg-docs) to allow
|
|
||||||
> access from known IP addresses only.
|
|
||||||
5. Click **Launch**.
|
|
||||||
6. You will be prompted to create a keypair.
|
|
||||||
> A key pair consists of a public key that AWS stores, and a private key file
|
|
||||||
> that you store. For Linux AMIs, the private key file allows you to
|
|
||||||
> securely SSH into your instance.
|
|
||||||
7. From the dropdown choose "create a new pair", give the key pair a name.
|
|
||||||
8. Click **Download Key Pair**. This is necessary before you proceed. A `.pem`
|
|
||||||
file will be downloaded. make sure you store is in a safe location because it
|
|
||||||
can't be retrieved once we move on.
|
|
||||||
9. Finally, click **Launch Instances**.
|
|
||||||
|
|
||||||
[ec2-home]: https://console.aws.amazon.com/ec2/v2/home
|
|
||||||
[ec2-sg-docs]: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-network-security.html?icmpid=docs_ec2_console
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Installing code-server onto an AWS Instance
|
|
||||||
|
|
||||||
1. First head to your [EC2 dashboard](ec2-home) and choose **Instances** on the
|
|
||||||
left sidebar.
|
|
||||||
2. Select the instance you just created, and in the description tab at the
|
|
||||||
bottom of the screen copy the **Public DNS (IPv4)** address using the copy to
|
|
||||||
clipboard button.
|
|
||||||
3. Open a terminal on your computer and use the following command to SSH into
|
|
||||||
your EC2 instance. If you're using Windows, you can use [PuTTY](putty-guide)
|
|
||||||
to open an SSH connection.
|
|
||||||
```
|
|
||||||
ssh -i "path/to/your/keypair.pem" ubuntu@(paste the public DNS here)
|
|
||||||
```
|
|
||||||
> For example: `ssh -i "/Users/John/Downloads/TestInstance.pem" ubuntu@ec2-3-45-678-910.compute-1.amazonaws.co`
|
|
||||||
4. If you get a warning about an unknown server key fingerprint, type "yes" to
|
|
||||||
approve the remote host.
|
|
||||||
5. You should see a prompt for your EC2 instance like so:
|
|
||||||
<img src="../../assets/aws_ubuntu.png">
|
|
||||||
6. At this point it is time to download the `code-server` binary. We will, of
|
|
||||||
course, want the linux version. Find the latest code-server release from the
|
|
||||||
[GitHub releases](code-server-latest) page.
|
|
||||||
7. Right click the Linux x64 `.tar.gz` release asset and copy the URL. In the
|
|
||||||
SSH terminal, run the following command:
|
|
||||||
```
|
|
||||||
wget (paste the URL here)
|
|
||||||
```
|
|
||||||
8. Extract the downloaded file with the following command:
|
|
||||||
```
|
|
||||||
tar -xvzf code-server*.tar.gz
|
|
||||||
```
|
|
||||||
9. Navigate to extracted directory with this command:
|
|
||||||
```
|
|
||||||
cd code-server*/
|
|
||||||
```
|
|
||||||
10. Ensure the code-server binary is executable with the following command:
|
|
||||||
```
|
|
||||||
chmod +x code-server
|
|
||||||
```
|
|
||||||
11. Finally, to start code-server run this command:
|
|
||||||
```
|
|
||||||
./code-server
|
|
||||||
```
|
|
||||||
12. code-server will start up, and the password will be printed in the output.
|
|
||||||
Make sure to copy the password for the next step.
|
|
||||||
13. Open your browser and visit `https://$public_ip:8443/` (where `$public_ip`
|
|
||||||
is your AWS instance's public IP address). You will be greeted with a page
|
|
||||||
similar to the following screenshot. code-server is using a self-signed SSL
|
|
||||||
certificate for easy setup. In Chrome/Chromium, click **Advanced** then
|
|
||||||
click **proceed anyway**. In Firefox, click **Advanced**, then **Add
|
|
||||||
Exception**, then finally **Confirm Security Exception**.
|
|
||||||
<img src="../../assets/chrome_warning.png">
|
|
||||||
|
|
||||||
[putty-guide]: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/putty.html
|
|
||||||
[code-server-latest]: https://github.com/cdr/code-server/releases/latest
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Post Installation Steps
|
|
||||||
|
|
||||||
To ensure the connection between you and your server is encrypted, view our
|
|
||||||
guides on [securing your setup](security-guide).
|
|
||||||
|
|
||||||
For instructions on how to keep the server running after you end your SSH
|
|
||||||
session please checkout [how to use systemd](systemd-guide). systemd will run
|
|
||||||
code-server for you in the background as a service and restart it for you if it
|
|
||||||
crashes.
|
|
||||||
|
|
||||||
[security-guide]: ../../security/index.md
|
|
||||||
[systemd-guide]: https://www.digitalocean.com/community/tutorials/how-to-configure-a-linux-service-to-start-automatically-after-a-crash-or-reboot-part-1-practical-examples
|
|
|
@ -1,125 +0,0 @@
|
||||||
# Deploy on DigitalOcean
|
|
||||||
|
|
||||||
This tutorial shows you how to deploy `code-server` to a single node running on DigitalOcean.
|
|
||||||
|
|
||||||
If you're just starting out, we recommend
|
|
||||||
[installing code-server locally](self-hosted-docs). It takes only a few minutes
|
|
||||||
and lets you try out all of the features locally.
|
|
||||||
|
|
||||||
If you get stuck or need help at anytime, [file an issue](create-issue),
|
|
||||||
[tweet (@coderhq)](twitter-coderhq) or [email](email-coder).
|
|
||||||
|
|
||||||
[self-hosted-docs]: ../../self-hosted/index.md
|
|
||||||
[create-issue]: https://github.com/cdr/code-server/issues/new?title=Improve+DigitalOcean+quickstart+guide
|
|
||||||
[twitter-coderhq]: https://twitter.com/coderhq
|
|
||||||
[email-coder]: mailto:support@coder.com?subject=DigitalOcean%20quickstart%20guide
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Recommended: Using the Marketplace
|
|
||||||
|
|
||||||
[![Create a Droplet](../../assets/do-new-droplet-btn.svg)](https://marketplace.digitalocean.com/apps/code-server?action=deploy)
|
|
||||||
|
|
||||||
1. On the **Create Droplets** page, choose a plan for your new code-server
|
|
||||||
instance. We recommend picking an instance with at least 4 GB of RAM and 2
|
|
||||||
CPU cores, or more depending on team size and number of
|
|
||||||
repositories/languages enabled.
|
|
||||||
2. Optionally enable backups and add block storage.
|
|
||||||
3. Choose the closest available region to your physical location to reduce
|
|
||||||
latency.
|
|
||||||
4. Select an SSH key that you already have in your account, or click **New SSH
|
|
||||||
Key** and follow the tutorial on how to make your own SSH key.
|
|
||||||
5. Click **Create Droplet**, then click on the droplet to expand it.
|
|
||||||
6. While you're waiting for the droplet to deploy, copy the **IPv4** address.
|
|
||||||
7. Once the droplet is ready, connect using SSH with the key you specified or
|
|
||||||
created earlier. You should be greeted with information on how to access your
|
|
||||||
code-server instance and how to view/change the password.
|
|
||||||
> You can SSH into your server using PuTTY or by running
|
|
||||||
> `ssh root@(paste ipv4 address here)`.
|
|
||||||
8. In the droplet's terminal, run `cat /etc/code-server/pass` to view the
|
|
||||||
code-server password.
|
|
||||||
9. Open your browser and visit `https://$public_ip` (where `$public_ip`
|
|
||||||
is your Droplet's public IP address). You will be greeted with a page similar
|
|
||||||
to the following screenshot. code-server is using a self-signed SSL
|
|
||||||
certificate for easy setup. In Chrome/Chromium, click **Advanced** then
|
|
||||||
click **proceed anyway**. In Firefox, click **Advanced**, then **Add
|
|
||||||
Exception**, then finally **Confirm Security Exception**.
|
|
||||||
<img src="../../assets/chrome_warning.png">
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Using the "Create Droplets" Wizard
|
|
||||||
|
|
||||||
If you used the Marketplace to set up code-server, you don't need to follow this
|
|
||||||
section.
|
|
||||||
|
|
||||||
[Open your DigitalOcean dashboard](create-droplet) to create a new droplet.
|
|
||||||
|
|
||||||
1. **Choose an image:** Select the **Distributions** tab and then choose
|
|
||||||
**Ubuntu 18.04.3 (LTS) x64**.
|
|
||||||
2. **Choose a size:** We recommend at least 4GB RAM and 2 CPU, or more depending
|
|
||||||
on team size and number of repositories/languages enabled.
|
|
||||||
3. Select an SSH key that you already have in your account, or click **New SSH
|
|
||||||
Key** and follow the tutorial on how to make your own SSH key.
|
|
||||||
4. Click **Create Droplet**, then click on the droplet to expand it.
|
|
||||||
5. While you're waiting for the droplet to deploy, copy the **IPv4** address.
|
|
||||||
6. Once the droplet is ready, connect using SSH with the key you specified or
|
|
||||||
created earlier. You should be greeted with information on how to access your
|
|
||||||
code-server instance and how to view/change the password.
|
|
||||||
> You can SSH into your server using PuTTY or by running
|
|
||||||
> `ssh root@(paste ipv4 address here)`.
|
|
||||||
7. If you get a warning about an unknown server key fingerprint, type "yes" to
|
|
||||||
approve the remote host.
|
|
||||||
8. You should see a prompt for your Droplet like so:
|
|
||||||
<img src="../../assets/digitalocean_ubuntu.png">
|
|
||||||
9. At this point it is time to download the `code-server` binary. We will, of
|
|
||||||
course, want the linux version. Find the latest code-server release from the
|
|
||||||
[GitHub releases](code-server-latest) page.
|
|
||||||
10. Right click the Linux x64 `.tar.gz` release asset and copy the URL. In the
|
|
||||||
SSH terminal, run the following command:
|
|
||||||
```
|
|
||||||
wget (paste the URL here)
|
|
||||||
```
|
|
||||||
11. Extract the downloaded file with the following command:
|
|
||||||
```
|
|
||||||
tar -xvzf code-server*.tar.gz
|
|
||||||
```
|
|
||||||
12. Navigate to extracted directory with this command:
|
|
||||||
```
|
|
||||||
cd code-server*/
|
|
||||||
```
|
|
||||||
13. Ensure the code-server binary is executable with the following command:
|
|
||||||
```
|
|
||||||
chmod +x code-server
|
|
||||||
```
|
|
||||||
14. Finally, to start code-server run this command:
|
|
||||||
```
|
|
||||||
./code-server
|
|
||||||
```
|
|
||||||
12. code-server will start up, and the password will be printed in the output.
|
|
||||||
Make sure to copy the password for the next step.
|
|
||||||
13. Open your browser and visit `https://$public_ip:8443/` (where `$public_ip`
|
|
||||||
is your Droplet's public IP address). You will be greeted with a page
|
|
||||||
similar to the following screenshot. code-server is using a self-signed SSL
|
|
||||||
certificate for easy setup. In Chrome/Chromium, click **Advanced** then
|
|
||||||
click **proceed anyway**. In Firefox, click **Advanced**, then **Add
|
|
||||||
Exception**, then finally **Confirm Security Exception**.
|
|
||||||
<img src="../../assets/chrome_warning.png">
|
|
||||||
|
|
||||||
[create-droplet]: https://cloud.digitalocean.com/droplets/new
|
|
||||||
[code-server-latest]: https://github.com/cdr/code-server/releases/latest
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Post Installation Steps
|
|
||||||
|
|
||||||
To ensure the connection between you and your server is encrypted, view our
|
|
||||||
guides on [securing your setup](security-guide).
|
|
||||||
|
|
||||||
For instructions on how to keep the server running after you end your SSH
|
|
||||||
session please checkout [how to use systemd](systemd-guide). systemd will run
|
|
||||||
code-server for you in the background as a service and restart it for you if it
|
|
||||||
crashes. (Note: this doesn't apply for users of the Marketplace Droplet image.)
|
|
||||||
|
|
||||||
[security-guide]: ../../security/index.md
|
|
||||||
[systemd-guide]: https://www.digitalocean.com/community/tutorials/how-to-configure-a-linux-service-to-start-automatically-after-a-crash-or-reboot-part-1-practical-examples
|
|
|
@ -1,101 +0,0 @@
|
||||||
# Deploy on Google Cloud Platform
|
|
||||||
|
|
||||||
This tutorial shows you how to deploy `code-server` to a single node running on
|
|
||||||
Google Cloud Platform.
|
|
||||||
|
|
||||||
If you're just starting out, we recommend
|
|
||||||
[installing code-server locally](self-hosted-docs). It takes only a few minutes
|
|
||||||
and lets you try out all of the features locally.
|
|
||||||
|
|
||||||
If you get stuck or need help at anytime, [file an issue](create-issue),
|
|
||||||
[tweet (@coderhq)](twitter-coderhq) or [email](email-coder).
|
|
||||||
|
|
||||||
[self-hosted-docs]: ../../self-hosted/index.md
|
|
||||||
[create-issue]: https://github.com/cdr/code-server/issues/new?title=Improve+Google+Cloud+quickstart+guide
|
|
||||||
[twitter-coderhq]: https://twitter.com/coderhq
|
|
||||||
[email-coder]: mailto:support@coder.com?subject=Google%20Cloud%20quickstart%20guide
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Deploy to Google Cloud VM
|
|
||||||
|
|
||||||
[Open your Google Cloud console](create-instance) to create a new VM instance.
|
|
||||||
|
|
||||||
1. Click **Create Instance**.
|
|
||||||
2. Choose an appropriate machine type (we recommend 2 vCPU and 7.5 GB RAM, or
|
|
||||||
more depending on team size and number of repositories/languages enabled).
|
|
||||||
3. Choose **Ubuntu 16.04 LTS** as your boot disk.
|
|
||||||
4. Expand the **Management, security, disks, networking, sole tenancy** section,
|
|
||||||
go to the **Networking** tab, then under network tags add `code-server`.
|
|
||||||
5. Create your VM, and **take note** of its public IP address.
|
|
||||||
6. Visit **VPC networks** in the console and go to **Firewall rules**. Create a
|
|
||||||
new firewall rule called `http-8443`. Under **Target tags**, add
|
|
||||||
`code-server`, and under **Protocols and ports** tick **Specified protocols and
|
|
||||||
ports** and **tcp**. Beside **tcp**, add `8443`, then create the rule.
|
|
||||||
|
|
||||||
[create-instance]: https://console.cloud.google.com/compute/instances
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Final Steps
|
|
||||||
|
|
||||||
Please [set up Google Cloud SDK](gcloud-sdk) on your local machine, or access
|
|
||||||
your instance terminal using another method.
|
|
||||||
|
|
||||||
<!-- TODO: add a screenshot of the initial terminal like other guides -->
|
|
||||||
|
|
||||||
1. SSH into your Google Cloud VM:
|
|
||||||
```
|
|
||||||
gcloud compute ssh --zone [region] [instance name]
|
|
||||||
```
|
|
||||||
2. At this point it is time to download the `code-server` binary. We will, of
|
|
||||||
course, want the linux version. Find the latest code-server release from the
|
|
||||||
[GitHub releases](code-server-latest) page.
|
|
||||||
3. Right click the Linux x64 `.tar.gz` release asset and copy the URL. In the
|
|
||||||
SSH terminal, run the following command:
|
|
||||||
```
|
|
||||||
wget (paste the URL here)
|
|
||||||
```
|
|
||||||
4. Extract the downloaded file with the following command:
|
|
||||||
```
|
|
||||||
tar -xvzf code-server*.tar.gz
|
|
||||||
```
|
|
||||||
5. Navigate to extracted directory with this command:
|
|
||||||
```
|
|
||||||
cd code-server*/
|
|
||||||
```
|
|
||||||
6. Ensure the code-server binary is executable with the following command:
|
|
||||||
```
|
|
||||||
chmod +x code-server
|
|
||||||
```
|
|
||||||
7. Finally, to start code-server run this command:
|
|
||||||
```
|
|
||||||
./code-server
|
|
||||||
```
|
|
||||||
8. code-server will start up, and the password will be printed in the output.
|
|
||||||
Make sure to copy the password for the next step.
|
|
||||||
9. Open your browser and visit `https://$public_ip:8443/` (where `$public_ip`
|
|
||||||
is your Instance's public IP address). You will be greeted with a page
|
|
||||||
similar to the following screenshot. code-server is using a self-signed SSL
|
|
||||||
certificate for easy setup. In Chrome/Chromium, click **Advanced** then
|
|
||||||
click **proceed anyway**. In Firefox, click **Advanced**, then **Add
|
|
||||||
Exception**, then finally **Confirm Security Exception**.
|
|
||||||
<img src="../../assets/chrome_warning.png">
|
|
||||||
|
|
||||||
[gcloud-sdk]: https://cloud.google.com/sdk/docs/
|
|
||||||
[code-server-latest]: https://github.com/cdr/code-server/releases/latest
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Post Installation Steps
|
|
||||||
|
|
||||||
To ensure the connection between you and your server is encrypted, view our
|
|
||||||
guides on [securing your setup](security-guide).
|
|
||||||
|
|
||||||
For instructions on how to keep the server running after you end your SSH
|
|
||||||
session please checkout [how to use systemd](systemd-guide). systemd will run
|
|
||||||
code-server for you in the background as a service and restart it for you if it
|
|
||||||
crashes.
|
|
||||||
|
|
||||||
[security-guide]: ../../security/index.md
|
|
||||||
[systemd-guide]: https://www.digitalocean.com/community/tutorials/how-to-configure-a-linux-service-to-start-automatically-after-a-crash-or-reboot-part-1-practical-examples
|
|
Before Width: | Height: | Size: 48 KiB |
Before Width: | Height: | Size: 30 KiB |
Before Width: | Height: | Size: 137 KiB |
Before Width: | Height: | Size: 42 KiB |
|
@ -1,24 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<svg width="200px" height="40px" viewBox="0 0 200 40" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
|
||||||
<!-- Generator: Sketch 52.5 (67469) - http://www.bohemiancoding.com/sketch -->
|
|
||||||
<title>do-btn-blue-ghost</title>
|
|
||||||
<desc>Created with Sketch.</desc>
|
|
||||||
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
|
||||||
<g id="Partner-welcome-kit-Copy-3" transform="translate(-651.000000, -828.000000)">
|
|
||||||
<g id="do-btn-blue-ghost" transform="translate(651.000000, 828.000000)">
|
|
||||||
<rect id="Rectangle-Copy-4" stroke="#0069FF" x="0.5" y="0.5" width="199" height="39" rx="6"></rect>
|
|
||||||
<path d="M6,0 L47,0 L47,40 L6,40 C2.6862915,40 4.05812251e-16,37.3137085 0,34 L-8.8817842e-16,6 C-1.29399067e-15,2.6862915 2.6862915,6.08718376e-16 6,0 Z" id="Rectangle-Copy-5" fill="#0069FF"></path>
|
|
||||||
<g id="DO_Logo_horizontal_blue-Copy-3" transform="translate(13.000000, 10.000000)" fill="#FFFFFF">
|
|
||||||
<path d="M10.0098493,20 L10.0098493,16.1262429 C14.12457,16.1262429 17.2897398,12.0548452 15.7269372,7.74627862 C15.1334679,6.14538921 13.8674,4.86072487 12.2650328,4.28756693 C7.952489,2.72620566 3.87733294,5.88845634 3.87733294,9.99938223 C3.87733294,9.99938223 3.87733294,9.99938223 3.87733294,9.99938223 L0,9.99938223 C0,3.45747613 6.3303395,-1.64165309 13.1948014,0.492866119 C16.2017127,1.42177726 18.57559,3.81322933 19.5053586,6.79760341 C21.6418482,13.6754986 16.5577943,20 10.0098493,20 Z" id="XMLID_49_"></path>
|
|
||||||
<polygon id="XMLID_47_" points="9.52380952 16.1904762 5.71428571 16.1904762 5.71428571 12.3809524 5.71428571 12.3809524 9.52380952 12.3809524 9.52380952 12.3809524"></polygon>
|
|
||||||
<polygon id="XMLID_46_" points="6.66666667 19.047619 3.80952381 19.047619 3.80952381 19.047619 3.80952381 16.1904762 6.66666667 16.1904762"></polygon>
|
|
||||||
<polygon id="XMLID_45_" points="3.80952381 16.1904762 0.952380952 16.1904762 0.952380952 16.1904762 0.952380952 13.3333333 0.952380952 13.3333333 3.80952381 13.3333333 3.80952381 13.3333333"></polygon>
|
|
||||||
</g>
|
|
||||||
<!-- Modified to add GitHub font-family after DigitalOcean's font-family, otherwise it looks bad on GitHub -->
|
|
||||||
<text id="Create-a-Droplet-Copy-3" font-family="Sailec-Medium, Sailec, -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol" font-size="16" font-weight="400" fill="#0069FF">
|
|
||||||
<tspan x="58" y="26">Create a Droplet</tspan>
|
|
||||||
</text>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 2.7 KiB |
After Width: | Height: | Size: 2.3 MiB |
Before Width: | Height: | Size: 603 KiB |
Before Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 58 KiB |
|
@ -0,0 +1,75 @@
|
||||||
|
# Installing code-server in your ChromiumOS/ChromeOS/CloudReady machine
|
||||||
|
|
||||||
|
This guide will show you how to install code-server into your CrOS machine.
|
||||||
|
|
||||||
|
## Using Crostini
|
||||||
|
|
||||||
|
One of the easier ways to run code-server is via
|
||||||
|
[Crostini](https://www.aboutchromebooks.com/tag/project-crostini/), the Linux
|
||||||
|
apps support feature in CrOS. Make sure you have enough RAM, HDD space and your
|
||||||
|
CPU has VT-x/ AMD-V support. If your chromebook has this, then you are
|
||||||
|
qualified to use Crostini.
|
||||||
|
|
||||||
|
If you are running R69, you might want to enable this on
|
||||||
|
[Chrome Flags](chrome://flags/#enable-experimental-crostini-ui).
|
||||||
|
If you run R72, however, this is already enabled for you.
|
||||||
|
|
||||||
|
After checking your prerequisites, follow the steps in [the self-host install guide](index.md)
|
||||||
|
on installing code-server. Once done, make sure code-server works by running
|
||||||
|
it. After running it, simply go to `penguin.linux.test:8080` to access
|
||||||
|
code-server. Now you should be greeted with this screen. If you did,
|
||||||
|
congratulations, you have installed code-server in your Chromebook!
|
||||||
|
|
||||||
|
![code-server on Chromebook](assets/cros.png)
|
||||||
|
|
||||||
|
Alternatively, if you ran code-server in another container and you need the IP
|
||||||
|
for that specific container, simply go to Termina's shell via `crosh` and type
|
||||||
|
`vsh termina`.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
Loading extra module: /usr/share/crosh/dev.d/50-crosh.sh
|
||||||
|
Welcome to crosh, the Chrome OS developer shell.
|
||||||
|
|
||||||
|
If you got here by mistake, don't panic! Just close this tab and carry on.
|
||||||
|
|
||||||
|
Type 'help' for a list of commands.
|
||||||
|
|
||||||
|
If you want to customize the look/behavior, you can use the options page.
|
||||||
|
Load it by using the Ctrl+Shift+P keyboard shortcut.
|
||||||
|
|
||||||
|
crosh> vsh termina
|
||||||
|
(termina) chronos@localhost ~ $
|
||||||
|
```
|
||||||
|
While in termina, run `lxc list`. It should output the list of running containers.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
(termina) chronos@localhost ~ $ lxc list
|
||||||
|
+---------|---------|-----------------------|------|------------|-----------+
|
||||||
|
| NAME | STATE | IPV4 | IPV6 | TYPE | SNAPSHOTS |
|
||||||
|
+---------|---------|-----------------------|------|------------|-----------+
|
||||||
|
| penguin | RUNNING | 100.115.92.199 (eth0) | | PERSISTENT | 0 |
|
||||||
|
+---------|---------|-----------------------|------|------------|-----------+
|
||||||
|
(termina) chronos@localhost ~ $
|
||||||
|
```
|
||||||
|
|
||||||
|
For this example, we show the default `penguin` container, which is exposed on
|
||||||
|
`eth0` at 100.115.92.199. Simply enter the IP of the container where the
|
||||||
|
code-server runs to Chrome.
|
||||||
|
|
||||||
|
## Using Crouton
|
||||||
|
|
||||||
|
[Crouton](https://github.com/dnschneid/crouton) is one of the old ways to get a
|
||||||
|
running full Linux via `chroot` on a Chromebook. To use crouton, enable
|
||||||
|
developer mode and go to `crosh`. This time, run `shell`, which should drop you
|
||||||
|
to `bash`.
|
||||||
|
|
||||||
|
Make sure you downloaded `crouton`, if so, go ahead and run it under
|
||||||
|
`~/Downloads`. After installing your chroot container via crouton, go ahead and
|
||||||
|
enter `enter-chroot` to enter your container.
|
||||||
|
|
||||||
|
Follow the instructions set in [the self-host install guide](index.md) to
|
||||||
|
install code-server. After that is done, run `code-server` and verify it works
|
||||||
|
by going to `localhost:8080`.
|
||||||
|
|
||||||
|
> At this point in writing, `localhost` seems to work in this method. However,
|
||||||
|
> the author is not sure if it applies still to newer Chromebooks.
|
|
@ -0,0 +1,73 @@
|
||||||
|
# Set up instance
|
||||||
|
## EC2 on AWS
|
||||||
|
- Click **Launch Instance** from your [EC2 dashboard](https://console.aws.amazon.com/ec2/v2/home).
|
||||||
|
- Select the Ubuntu Server 18.04 LTS (HVM), SSD Volume Type
|
||||||
|
- Select an appropriate instance size (we recommend t2.medium/large, depending
|
||||||
|
on team size and number of repositories/languages enabled), then
|
||||||
|
**Next: Configure Instance Details**.
|
||||||
|
- Select **Next: ...** until you get to the **Configure Security Group** page,
|
||||||
|
then add a **Custom TCP Rule** rule with port range set to `8080` and source
|
||||||
|
set to "Anywhere".
|
||||||
|
> Rules with source of 0.0.0.0/0 allow all IP addresses to access your
|
||||||
|
> instance. We recommend setting [security group rules](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-network-security.html?icmpid=docs_ec2_console)
|
||||||
|
> to allow access from known IP addresses only.
|
||||||
|
- Click **Launch**.
|
||||||
|
- You will be prompted to create a key pair.
|
||||||
|
- From the dropdown choose "create a new pair", give the key pair a name.
|
||||||
|
- Click **Download Key Pair** and store the file in a safe place.
|
||||||
|
- Click **Launch Instances**.
|
||||||
|
- Head to your [EC2 dashboard](https://console.aws.amazon.com/ec2/v2/home)
|
||||||
|
and choose instances from the left panel.
|
||||||
|
- In the description of your EC2 instance copy the public DNS (iPv4) address
|
||||||
|
using the copy to clipboard button.
|
||||||
|
- Open a terminal on your computer and SSH into your instance:
|
||||||
|
```
|
||||||
|
ssh -i ${path to key pair} ubuntu@${public address}
|
||||||
|
```
|
||||||
|
|
||||||
|
## DigitalOcean
|
||||||
|
[Open your DigitalOcean dashboard](https://cloud.digitalocean.com/droplets/new)
|
||||||
|
to create a new droplet
|
||||||
|
|
||||||
|
- **Choose an image -** Select the **Distributions** tab and then choose Ubuntu.
|
||||||
|
- **Choose a size -** We recommend at least 4GB RAM and 2 CPU, more depending
|
||||||
|
on team size and number of repositories/languages enabled.
|
||||||
|
- Launch your instance.
|
||||||
|
- Open a terminal on your computer and SSH into your instance:
|
||||||
|
```
|
||||||
|
ssh root@${instance ip}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Google Cloud
|
||||||
|
> Pre-requisite: Set up the [Google Cloud SDK](https://cloud.google.com/sdk/docs/)
|
||||||
|
> on your local machine
|
||||||
|
|
||||||
|
- [Open your Google Cloud console](https://console.cloud.google.com/compute/instances)
|
||||||
|
to create a new VM instance and click **Create Instance**.
|
||||||
|
- Choose an appropriate machine type (we recommend 2 vCPU and 7.5 GB RAM, more
|
||||||
|
depending on team size and number of repositories/languages enabled).
|
||||||
|
- Choose Ubuntu 16.04 LTS as your boot disk.
|
||||||
|
- Expand the "Management, security, disks, networking, sole tenancy" section,
|
||||||
|
go to the "Networking" tab, then under network tags add "code-server".
|
||||||
|
- Create your VM, and **take note** of its public IP address.
|
||||||
|
- Visit "VPC network" in the console and go to "Firewall rules". Create a new
|
||||||
|
firewall rule called "http-8080". Under "Target tags" add "code-server", and
|
||||||
|
under "Protocols and ports" tick "Specified protocols and ports" and "tcp".
|
||||||
|
Beside "tcp", add "8080", then create the rule.
|
||||||
|
- Open a terminal on your computer and SSH into your Google Cloud VM:
|
||||||
|
```
|
||||||
|
gcloud compute ssh --zone ${region} ${instance name}
|
||||||
|
```
|
||||||
|
# Run code-server
|
||||||
|
- Download the latest code-server release from the
|
||||||
|
[releases page](https://github.com/cdr/code-server/releases/latest)
|
||||||
|
to the instance, extract the file, then run the code-server binary:
|
||||||
|
```
|
||||||
|
wget https://github.com/cdr/code-server/releases/download/{version}/code-server{version}-linux-x64.tar.gz
|
||||||
|
tar -xvzf code-server{version}-linux-x64.tar.gz
|
||||||
|
cd code-server{version}-linux-x64
|
||||||
|
./code-server
|
||||||
|
```
|
||||||
|
- Open your browser and visit http://$public_ip:8080/ where `$public_ip` is
|
||||||
|
your instance's public IP address.
|
||||||
|
- For long-term use, set up a systemd service to run code-server.
|
|
@ -0,0 +1,15 @@
|
||||||
|
# Fail2Ban filter for code-server
|
||||||
|
|
||||||
|
[Definition]
|
||||||
|
|
||||||
|
failregex = ^INFO\s+Failed login attempt\s+{\"password\":\"(\\.|[^"])*\",\"remoteAddress\":\"<HOST>\"
|
||||||
|
|
||||||
|
# Use this instead for proxies (ensure the proxy is configured to send the
|
||||||
|
# X-Forwarded-For header).
|
||||||
|
# failregex = ^INFO\s+Failed login attempt\s+{\"password\":\"(\\.|[^"])*\",\"xForwardedFor\":\"<HOST>\"
|
||||||
|
|
||||||
|
ignoreregex =
|
||||||
|
|
||||||
|
datepattern = "timestamp":{EPOCH}}$
|
||||||
|
|
||||||
|
# Author: Dean Sheather
|
|
@ -10,7 +10,7 @@ metadata:
|
||||||
namespace: code-server
|
namespace: code-server
|
||||||
spec:
|
spec:
|
||||||
ports:
|
ports:
|
||||||
- port: 8443
|
- port: 8080
|
||||||
name: https
|
name: https
|
||||||
protocol: TCP
|
protocol: TCP
|
||||||
selector:
|
selector:
|
||||||
|
@ -62,7 +62,7 @@ spec:
|
||||||
imagePullPolicy: Always
|
imagePullPolicy: Always
|
||||||
name: code-servery
|
name: code-servery
|
||||||
ports:
|
ports:
|
||||||
- containerPort: 8443
|
- containerPort: 8080
|
||||||
name: https
|
name: https
|
||||||
volumeMounts:
|
volumeMounts:
|
||||||
- name: code-server-storage
|
- name: code-server-storage
|
||||||
|
@ -71,4 +71,3 @@ spec:
|
||||||
- name: code-server-storage
|
- name: code-server-storage
|
||||||
persistentVolumeClaim:
|
persistentVolumeClaim:
|
||||||
claimName: code-store
|
claimName: code-store
|
||||||
|
|
|
@ -10,7 +10,7 @@ metadata:
|
||||||
namespace: code-server
|
namespace: code-server
|
||||||
spec:
|
spec:
|
||||||
ports:
|
ports:
|
||||||
- port: 8443
|
- port: 8080
|
||||||
name: https
|
name: https
|
||||||
protocol: TCP
|
protocol: TCP
|
||||||
selector:
|
selector:
|
||||||
|
@ -39,5 +39,5 @@ spec:
|
||||||
imagePullPolicy: Always
|
imagePullPolicy: Always
|
||||||
name: code-server
|
name: code-server
|
||||||
ports:
|
ports:
|
||||||
- containerPort: 8443
|
- containerPort: 8080
|
||||||
name: https
|
name: https
|
|
@ -0,0 +1,35 @@
|
||||||
|
# Protecting code-server from bruteforce attempts
|
||||||
|
code-server outputs all failed login attempts, along with the IP address,
|
||||||
|
provided password, user agent and timestamp by default.
|
||||||
|
|
||||||
|
When using a reverse proxy such as Nginx or Apache, the remote address may
|
||||||
|
appear to be `127.0.0.1` or a similar address so `X-Forwarded-For` should be
|
||||||
|
used instead. Ensure that you are setting this value in your reverse proxy:
|
||||||
|
|
||||||
|
Nginx:
|
||||||
|
```
|
||||||
|
location / {
|
||||||
|
...
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Apache:
|
||||||
|
```
|
||||||
|
<VirtualEnv>
|
||||||
|
...
|
||||||
|
SetEnvIf X-Forwarded-For "^.*\..*\..*\..*" forwarded
|
||||||
|
...
|
||||||
|
</VirtualEnv>
|
||||||
|
```
|
||||||
|
|
||||||
|
It is extremely important that you ensure that your code-server instance is not
|
||||||
|
accessible from the internet (use localhost or block it in your firewall).
|
||||||
|
|
||||||
|
## Fail2Ban
|
||||||
|
Fail2Ban allows for automatically banning and logging repeated failed
|
||||||
|
authentication attempts for many applications through regex filters. A working
|
||||||
|
filter for code-server can be found in `./code-server.fail2ban.conf`. Once this
|
||||||
|
is installed and configured correctly, repeated failed login attempts should
|
||||||
|
automatically be banned from connecting to your server.
|
|
@ -0,0 +1,57 @@
|
||||||
|
# Quickstart Guide
|
||||||
|
1. Visit the [releases page](https://github.com/cdr/code-server/releases) and
|
||||||
|
download the latest binary for your operating system.
|
||||||
|
2. Unpack the downloaded file then run the binary.
|
||||||
|
3. In your browser navigate to `localhost:8080`.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
Run `code-server --help` to view available options.
|
||||||
|
|
||||||
|
### Encrypting traffic with HTTPS
|
||||||
|
To encrypt the traffic between the browser and server use `code-server --cert`
|
||||||
|
followed by the path to your certificate. Additionally, you can use certificate
|
||||||
|
keys with `--cert-key` followed by the path to your key. If you pass `--cert`
|
||||||
|
without any path code-server will generate a self-signed certificate.
|
||||||
|
|
||||||
|
You can use [Let's Encrypt](https://letsencrypt.org/) to get an SSL certificate
|
||||||
|
for free.
|
||||||
|
|
||||||
|
### Nginx Reverse Proxy
|
||||||
|
The trailing slashes are important.
|
||||||
|
|
||||||
|
```
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
listen [::]:80;
|
||||||
|
server_name code.example.com code.example.org;
|
||||||
|
location /some/path/ { # Or / if hosting at the root.
|
||||||
|
proxy_pass http://localhost:8080/;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header Upgrade $http_upgrade;
|
||||||
|
proxy_set_header Connection upgrade;
|
||||||
|
proxy_set_header Accept-Encoding gzip;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Apache Reverse Proxy
|
||||||
|
```
|
||||||
|
<VirtualHost *:80>
|
||||||
|
ServerName code.example.com
|
||||||
|
|
||||||
|
RewriteEngine On
|
||||||
|
RewriteCond %{HTTP:Upgrade} =websocket [NC]
|
||||||
|
RewriteRule /(.*) ws://localhost:8080/$1 [P,L]
|
||||||
|
RewriteCond %{HTTP:Upgrade} !=websocket [NC]
|
||||||
|
RewriteRule /(.*) http://localhost:8080/$1 [P,L]
|
||||||
|
|
||||||
|
ProxyRequests off
|
||||||
|
|
||||||
|
RequestHeader set X-Forwarded-Proto https
|
||||||
|
RequestHeader set X-Forwarded-Port 443
|
||||||
|
|
||||||
|
ProxyPass / http://localhost:8080/ nocanon
|
||||||
|
ProxyPassReverse / http://localhost:8080/
|
||||||
|
|
||||||
|
</VirtualHost>
|
||||||
|
```
|
|
@ -1,11 +0,0 @@
|
||||||
# Fail2Ban filter for code-server
|
|
||||||
|
|
||||||
[Definition]
|
|
||||||
|
|
||||||
failregex = ^INFO\s+Failed login attempt\s+{\"password\":\"(\\.|[^"])*\",\"remote_address\":\"<HOST>\"
|
|
||||||
|
|
||||||
ignoreregex =
|
|
||||||
|
|
||||||
datepattern = "timestamp":{EPOCH}}$
|
|
||||||
|
|
||||||
# Author: Dean Sheather
|
|
|
@ -1,44 +0,0 @@
|
||||||
# Protecting code-server from Bruteforce Attempts
|
|
||||||
|
|
||||||
<!-- TODO: remove this notice -->
|
|
||||||
### **NOTE: FAILED LOGIN ATTEMPT LOGGING IS NOT IN THE CURRENT VERSION AND WILL BE RELEASED IN V2.**
|
|
||||||
|
|
||||||
code-server outputs all failed login attempts, along with the IP address,
|
|
||||||
provided password, user agent and timestamp by default. When using a reverse
|
|
||||||
proxy such as Nginx or Apache, the remote address may appear to be `127.0.0.1`
|
|
||||||
or a similar address unless the `--trust-proxy` argument is provided to
|
|
||||||
code-server.
|
|
||||||
|
|
||||||
When used with the `--trust-proxy` argument, code-server will use the last IP in
|
|
||||||
`X-Forwarded-For` (if provided) instead of the remote socket address. Ensure
|
|
||||||
that you are setting this value in your reverse proxy:
|
|
||||||
|
|
||||||
Nginx:
|
|
||||||
```
|
|
||||||
location / {
|
|
||||||
...
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
...
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Apache:
|
|
||||||
```
|
|
||||||
<VirtualEnv>
|
|
||||||
...
|
|
||||||
SetEnvIf X-Forwarded-For "^.*\..*\..*\..*" forwarded
|
|
||||||
...
|
|
||||||
</VirtualEnv>
|
|
||||||
```
|
|
||||||
|
|
||||||
It is extremely important that if you enable `--trust-proxy` you ensure your
|
|
||||||
code-server instance is not accessible from the internet (block it in your
|
|
||||||
firewall).
|
|
||||||
|
|
||||||
## Fail2Ban
|
|
||||||
|
|
||||||
Fail2Ban allows for automatically banning and logging repeated failed
|
|
||||||
authentication attempts for many applications through regex filters. A working
|
|
||||||
filter for code-server can be found in `./code-server.fail2ban.conf`. Once this
|
|
||||||
is installed and configured correctly, repeated failed login attempts should
|
|
||||||
automatically be banned from connecting to your server.
|
|
|
@ -1,8 +0,0 @@
|
||||||
# Security Guides
|
|
||||||
|
|
||||||
We recommend users running code-server setup SSL and fail2ban on their
|
|
||||||
instances for improved security and resilience to attacks.
|
|
||||||
|
|
||||||
* [Self-signed SSL guide](./ssl.md)
|
|
||||||
* [Let's Encrypt SSL guide](./ssl-certbot.md)
|
|
||||||
* [Fail2Ban setup guide](./fail2ban.md)
|
|
|
@ -1,63 +0,0 @@
|
||||||
# Generate a Certificate Using Let's Encrypt 🔒
|
|
||||||
|
|
||||||
To get around the certificate warnings in Chrome, you might want to install a
|
|
||||||
certificate from a trusted Certificate Authority (CA). Luckily, there are CAs
|
|
||||||
like [Let's Encrypt](lets-encrypt) which provide certificates for free.
|
|
||||||
|
|
||||||
[lets-encrypt]: https://letsencrypt.org/
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Using Certbot
|
|
||||||
|
|
||||||
[Certbot](certbot) is the program we'll be using to issue certificates from
|
|
||||||
Let's Encrypt.
|
|
||||||
|
|
||||||
> Pre-requisites: You will need a domain name or subdomain pointed to the IP
|
|
||||||
> address of your server.
|
|
||||||
|
|
||||||
1. Install Certbot by heading to the [instructions page](certbot-instructions).
|
|
||||||
Select **None of the above** for the software and the right operating system
|
|
||||||
for your setup.
|
|
||||||
2. Follow the installation instructions, and stop once you get up to the part
|
|
||||||
where you run the `certbot certonly` command.
|
|
||||||
3. Ensure your code-server instance isn't running, and any other webservers that
|
|
||||||
could interfere are also stopped.
|
|
||||||
4. Run the following command, replacing `code.example.com` with the
|
|
||||||
hostname/domain you want to run your server on, to issue a certificate:
|
|
||||||
```
|
|
||||||
sudo certbot certonly --standalone -d code.example.com
|
|
||||||
```
|
|
||||||
5. Follow the prompts, providing your email address and accepting the terms
|
|
||||||
where required.
|
|
||||||
6. Once the process is complete, it should print the paths to the certificates
|
|
||||||
and keys that were generated. You can now restart any webservers you stopped
|
|
||||||
in step 2.
|
|
||||||
|
|
||||||
[certbot]: https://certbot.eff.org/
|
|
||||||
[certbot-instructions]: https://certbot.eff.org/instructions
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Starting code-server with a Certificate and Key
|
|
||||||
|
|
||||||
Just add the `--cert` and `--cert-key` flags when you run code-server:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
./code-server --cert=/etc/letsencrypt/live/code.example.com/fullchain.pem --cert-key=/etc/letsencrypt/live/code.example.com/privkey.pem
|
|
||||||
```
|
|
||||||
|
|
||||||
You can now verify that your SSL installation is working properly by checking
|
|
||||||
your site with [SSL Labs' SSL Test](ssl-labs-test).
|
|
||||||
|
|
||||||
[ssl-labs-test]: https://www.ssllabs.com/ssltest/
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Next Steps
|
|
||||||
|
|
||||||
You probably want to setup automatic renewal of your certificates, as they
|
|
||||||
expire every 3 months. You can find instructions on how to do this in
|
|
||||||
[Certbot's documentation](certbot-renew-docs).
|
|
||||||
|
|
||||||
[certbot-renew-docs]: https://certbot.eff.org/docs/using.html?highlight=hooks#renewing-certificates
|
|
|
@ -1,70 +0,0 @@
|
||||||
# Generate a Self-signed Certificate 🔒
|
|
||||||
|
|
||||||
code-server has the ability to secure your connection between client and server
|
|
||||||
using SSL/TSL certificates. By default, the server will start with an
|
|
||||||
unencrypted connection. We recommend Self-signed TLS/SSL certificates for
|
|
||||||
personal use of code-server or within an organization.
|
|
||||||
|
|
||||||
This guide will show you how to create a self-signed certificate and start
|
|
||||||
code-server using your certificate/key.
|
|
||||||
|
|
||||||
## TLS / HTTPS
|
|
||||||
|
|
||||||
You can specify any location that you want to save the certificate and key. In
|
|
||||||
this example, we will navigate to the root directory, create a folder called
|
|
||||||
`certs` and cd into it.
|
|
||||||
|
|
||||||
```shell
|
|
||||||
mkdir ~/certs && cd ~/certs
|
|
||||||
```
|
|
||||||
|
|
||||||
If you don't already have a TLS certificate and key, you can generate them with
|
|
||||||
the command below. They will be placed in `~/certs`.
|
|
||||||
|
|
||||||
```shell
|
|
||||||
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout ~/certs/MyKey.key -out ~/certs/MyCertificate.crt
|
|
||||||
```
|
|
||||||
|
|
||||||
You will be prompted to add some identifying information about your
|
|
||||||
organization:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
You are about to be asked to enter information that will be incorporated
|
|
||||||
into your certificate request.
|
|
||||||
What you are about to enter is what is called a Distinguished Name or a DN.
|
|
||||||
There are quite a few fields but you can leave some blank
|
|
||||||
For some fields there will be a default value,
|
|
||||||
If you enter '.', the field will be left blank.
|
|
||||||
-----
|
|
||||||
Country Name (2 letter code) [AU]:US
|
|
||||||
State or Province Name (full name) [Some-State]:TX
|
|
||||||
Locality Name (eg, city) []:Austin
|
|
||||||
Organization Name (eg, company) [Coder Technologies]:Coder
|
|
||||||
Organizational Unit Name (eg, section) []:Docs
|
|
||||||
Common Name (e.g. server FQDN or YOUR name) []:hostname.example.com
|
|
||||||
Email Address []:admin@example.com
|
|
||||||
```
|
|
||||||
|
|
||||||
> If you already have a TLS certificate and key, you can simply reference them
|
|
||||||
> in the `--cert` and `--cert-key` flags when launching code-server.
|
|
||||||
|
|
||||||
|
|
||||||
## Starting code-server with a Certificate and Key
|
|
||||||
|
|
||||||
Just add the `--cert` and `--cert-key` flags when you run code-server:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
./code-server --cert=~/certs/MyCertificate.crt --cert-key=~/certs/MyKey.key
|
|
||||||
```
|
|
||||||
|
|
||||||
> You should check that the
|
|
||||||
> `WARN No certificate specified. This could be insecure` are no longer visible
|
|
||||||
> in the output.
|
|
||||||
|
|
||||||
## Other Options
|
|
||||||
|
|
||||||
For larger organizations you may wish to rely on a trusted Certificate Authority
|
|
||||||
as opposed to a self-signed certificate. For more information on generating free
|
|
||||||
and open certificates for your site, please check out EFF's
|
|
||||||
[certbot](https://certbot.eff.org/). Certbot is a cli to generate certificates
|
|
||||||
using [LetsEncrypt](https://letsencrypt.org/).
|
|
|
@ -1,81 +0,0 @@
|
||||||
# Installng code-server on a ChromeOS/CloudReady machine
|
|
||||||
|
|
||||||
This guide will show you how to install code-server on your CrOS machine.
|
|
||||||
|
|
||||||
## Using Crostini
|
|
||||||
|
|
||||||
One of the easier ways to run code-server is via [Crostini](crostini), the Linux
|
|
||||||
apps support feature in CrOS. Make sure you have enough RAM, HDD space and your
|
|
||||||
CPU has VT-x/AMD-V support. If your Chromebook has this, then you are qualified
|
|
||||||
to use Crostini.
|
|
||||||
|
|
||||||
If you are running R69, you might want to enable this on
|
|
||||||
[Chrome Flags](r69-flag). If you run R72, however, this is already enabled for
|
|
||||||
you.
|
|
||||||
|
|
||||||
After checking your prerequisites, follow the steps in [the self-host install
|
|
||||||
guide](self-hosted-guide) on installing code-server. Once done, make sure
|
|
||||||
code-server works by running it, then simply go to `penguin.linux.test:8443` to
|
|
||||||
access code-server. You should be greeted with the following screen. If it
|
|
||||||
works, congratulations, you have installed code-server in your Chromebook!
|
|
||||||
|
|
||||||
![code-server on Chromebook](../assets/cros.png)
|
|
||||||
|
|
||||||
Alternatively, if you ran code-server in another container and you need the IP
|
|
||||||
for that specific container, simply go to Termina's shell via `crosh` and type
|
|
||||||
`vsh termina`.
|
|
||||||
|
|
||||||
```
|
|
||||||
Loading extra module: /usr/share/crosh/dev.d/50-crosh.sh
|
|
||||||
Welcome to crosh, the Chrome OS developer shell.
|
|
||||||
|
|
||||||
If you got here by mistake, don't panic! Just close this tab and carry on.
|
|
||||||
|
|
||||||
Type 'help' for a list of commands.
|
|
||||||
|
|
||||||
If you want to customize the look/behavior, you can use the options page.
|
|
||||||
Load it by using the Ctrl+Shift+P keyboard shortcut.
|
|
||||||
|
|
||||||
crosh> vsh termina
|
|
||||||
(termina) chronos@localhost ~ $
|
|
||||||
```
|
|
||||||
|
|
||||||
While in termina, run `lxc list`. It should output the list of running
|
|
||||||
containers.
|
|
||||||
|
|
||||||
```
|
|
||||||
(termina) chronos@localhost ~ $ lxc list
|
|
||||||
+---------+---------+-----------------------+------+------------+-----------+
|
|
||||||
| NAME | STATE | IPV4 | IPV6 | TYPE | SNAPSHOTS |
|
|
||||||
+---------+---------+-----------------------+------+------------+-----------+
|
|
||||||
| penguin | RUNNING | 100.115.92.199 (eth0) | | PERSISTENT | 0 |
|
|
||||||
+---------+---------+-----------------------+------+------------+-----------+
|
|
||||||
(termina) chronos@localhost ~ $
|
|
||||||
```
|
|
||||||
|
|
||||||
For this example, we show the default `penguin` container, which is exposed on
|
|
||||||
`eth0` at 100.115.92.199. Simply enter the IP of the container where code-server
|
|
||||||
is running into Chrome to access code-server.
|
|
||||||
|
|
||||||
[crostini]: https://www.aboutchromebooks.com/tag/project-crostini/
|
|
||||||
[r69-flag]: chrome://flags/#enable-experimental-crostini-ui
|
|
||||||
[self-hosted-guide]: ./index.md
|
|
||||||
|
|
||||||
## Using Crouton
|
|
||||||
|
|
||||||
[Crouton](crouton) is one of the old ways to get a running full Linux via
|
|
||||||
`chroot` on a Chromebook. To use crouton, enable developer mode and go to
|
|
||||||
`crosh`. This time, run `shell`, which should drop you to `bash`.
|
|
||||||
|
|
||||||
Make sure you downloaded `crouton`, if so, go ahead and run it under
|
|
||||||
`~/Downloads`. After installing your chroot container via crouton, go ahead and
|
|
||||||
enter `enter-chroot` to enter your container.
|
|
||||||
|
|
||||||
Follow the instructions set in [the self-host install guide](self-hosted-guide)
|
|
||||||
to install code-server. After that is done, run `code-server` and verify it
|
|
||||||
works by going to `localhost:8443`.
|
|
||||||
|
|
||||||
> At this point in writing, `localhost` seems to work in this method. However,
|
|
||||||
> it might not apply to newer Chromebooks.
|
|
||||||
|
|
||||||
[crouton]: https://github.com/dnschneid/crouton
|
|
|
@ -1,306 +0,0 @@
|
||||||
# Getting Started
|
|
||||||
|
|
||||||
This document pertains to Coder-specific implementation of VS Code: code-server.
|
|
||||||
For documentation on how to use VS Code itself, please refer to the official
|
|
||||||
[VS Code documentation](vscode-documentation).
|
|
||||||
|
|
||||||
If you get stuck or need help at anytime, [file an issue](create-issue),
|
|
||||||
[tweet (@coderhq)](twitter-coderhq) or [email](email-coder).
|
|
||||||
|
|
||||||
[vscode-documentation]: https://code.visualstudio.com/docs
|
|
||||||
[create-issue]: https://github.com/cdr/code-server/issues/new?title=Improve+self-hosted+quickstart+guide
|
|
||||||
[twitter-coderhq]: https://twitter.com/coderhq
|
|
||||||
[email-coder]: mailto:support@coder.com?subject=Self-hosted%20quickstart%20guide
|
|
||||||
|
|
||||||
|
|
||||||
## Quickstart Guide
|
|
||||||
|
|
||||||
It takes just a few minutes to get your own self-hosted server running. If
|
|
||||||
you've got a machine running macOS or Linux, you're ready to start the
|
|
||||||
binary which listens on port `8443` by default.
|
|
||||||
|
|
||||||
<!-- DO NOT CHANGE THIS TO A CODEBLOCK. We want line breaks for readability, but
|
|
||||||
backslashes to escape them do not work cross-platform. This uses line
|
|
||||||
breaks that are rendered but not copy-pasted to the clipboard. -->
|
|
||||||
|
|
||||||
1. Visit the [releases](code-server-releases) page and download the latest
|
|
||||||
release for your operating system.
|
|
||||||
2. Extract the archive and double click the executable to run in the current
|
|
||||||
directory.
|
|
||||||
3. Copy the password that appears in the output.
|
|
||||||
<img src="../assets/cli.png">
|
|
||||||
4. In your browser navigate to https://localhost:8443. You will be greeted with
|
|
||||||
an SSL warning as code-server uses a self-signed certificate (more on that
|
|
||||||
below). Skip the warning.
|
|
||||||
5. Login using the password from earlier.
|
|
||||||
|
|
||||||
Be careful about who you share your password with, as it will grant them full
|
|
||||||
access to your server.
|
|
||||||
|
|
||||||
[code-server-releases]: https://github.com/cdr/code-server/releases
|
|
||||||
|
|
||||||
|
|
||||||
### Security Warnings
|
|
||||||
|
|
||||||
When you visit your code-server instance, you will be greeted with a warning
|
|
||||||
page similar to the following screenshot. code-server is using a self-signed SSL
|
|
||||||
certificate for easy setup. In Chrome/Chromium, click **Advanced** then click
|
|
||||||
**proceed anyway**. In Firefox, click **Advanced**, then **Add Exception**,
|
|
||||||
then finally **Confirm Security Exception**.
|
|
||||||
<img src="../assets/chrome_warning.png">
|
|
||||||
|
|
||||||
|
|
||||||
## code-server Usage
|
|
||||||
|
|
||||||
You can bring up code-server usage by using `code-server --help`. Arguments let
|
|
||||||
you customize your working directory, host, port, SSL certificates, and more.
|
|
||||||
|
|
||||||
Flags can be supplied to code-server like `--flag-name value` or
|
|
||||||
`--flag-name=value`. To supply values with whitespace, use double quotes.
|
|
||||||
|
|
||||||
```
|
|
||||||
$ code-server --help
|
|
||||||
Usage: code-server [options]
|
|
||||||
|
|
||||||
Run VS Code on a remote server.
|
|
||||||
|
|
||||||
Options:
|
|
||||||
-V, --version output the version number
|
|
||||||
--cert <value>
|
|
||||||
--cert-key <value>
|
|
||||||
-e, --extensions-dir <dir> Override the main default path for user extensions.
|
|
||||||
--extra-extensions-dir [dir] Path to an extra user extension directory (repeatable). (default: [])
|
|
||||||
--extra-builtin-extensions-dir [dir] Path to an extra built-in extension directory (repeatable). (default: [])
|
|
||||||
-d --user-data-dir <dir> Specifies the directory that user data is kept in, useful when running as root.
|
|
||||||
-h, --host <value> Customize the hostname. (default: "0.0.0.0")
|
|
||||||
-o, --open Open in the browser on startup.
|
|
||||||
-p, --port <number> Port to bind on. (default: 8443)
|
|
||||||
-N, --no-auth Start without requiring authentication.
|
|
||||||
-H, --allow-http Allow http connections.
|
|
||||||
--disable-telemetry Disables ALL telemetry.
|
|
||||||
--socket <value> Listen on a UNIX socket. Host and port will be ignored when set.
|
|
||||||
--install-extension <value> Install an extension by its ID.
|
|
||||||
-h, --help output usage information
|
|
||||||
```
|
|
||||||
|
|
||||||
By default, code-server listens on `0.0.0.0:8443`. If you'd like to customize
|
|
||||||
this, use the `--host` and `--port` flags:
|
|
||||||
`code-server --host 127.0.0.1 --port 1234`.
|
|
||||||
|
|
||||||
You can instruct code-server to automatically open itself in your default
|
|
||||||
browser by using the `-o` or `--open` flag.
|
|
||||||
|
|
||||||
Use `code-server -d path/to/directory` to specify where code-server stores it's
|
|
||||||
configuration data. You can specify where extensions are installed using the
|
|
||||||
`-e`, `--extra-extensions-dir` and `--extra-builtin-extensions-dir` flags.
|
|
||||||
|
|
||||||
|
|
||||||
### SSL Certificates
|
|
||||||
|
|
||||||
To change the certificate code-server uses for HTTPS connections, specify a
|
|
||||||
certificate with `--cert` and a private key with `--cert-key`.
|
|
||||||
|
|
||||||
If you're using Let's Encrypt, you should be using the `fullchain.pem` file as
|
|
||||||
the certificate and `privkey.pem` as the private key.
|
|
||||||
|
|
||||||
```
|
|
||||||
code-server \
|
|
||||||
--cert /etc/letsencrypt/live/example.com/fullchain.pem \
|
|
||||||
--cert-key /etc/letsencrypt/live/example.com/privkey.pem
|
|
||||||
```
|
|
||||||
|
|
||||||
For more information on security and SSL configuration, please visit the
|
|
||||||
[security documentation](../security).
|
|
||||||
|
|
||||||
|
|
||||||
#### Telemetry
|
|
||||||
|
|
||||||
Telemetry can be disabled by using the `--disable-telemetry` flag or by setting
|
|
||||||
the `DISABLE_TELEMETRY` environment variable to `true`. If telemetry is enabled,
|
|
||||||
code-server will send the following data along with VS Code's telemetry data:
|
|
||||||
|
|
||||||
- Unique machine ID
|
|
||||||
- CPU core count and model
|
|
||||||
- Memory information
|
|
||||||
- Shell information (which shell you use)
|
|
||||||
- OS release and architecture
|
|
||||||
|
|
||||||
|
|
||||||
### Nginx Reverse Proxy
|
|
||||||
|
|
||||||
The following site configuration file works with code-server. When starting
|
|
||||||
code-server, be sure to provide the `--allow-http` and `--trust-proxy` flags so
|
|
||||||
Nginx can connect to code-server properly.
|
|
||||||
|
|
||||||
Some of these directives require a version of Nginx greater than or equal to
|
|
||||||
`1.13.0`, which might not be available in your distro's repositories. Check out
|
|
||||||
[Nginx's documentation](nginx-install) for more information on how to install
|
|
||||||
the latest version of Nginx from the official repository.
|
|
||||||
|
|
||||||
```
|
|
||||||
# HTTP configuration
|
|
||||||
server {
|
|
||||||
listen 80;
|
|
||||||
listen [::]:80;
|
|
||||||
server_name code.example.com code.example.org;
|
|
||||||
|
|
||||||
# If you're using CloudFlare, uncomment the following line.
|
|
||||||
# real_ip_header CF-Connecting-IP;
|
|
||||||
|
|
||||||
# Other security options.
|
|
||||||
add_header X-Frame-Options SAMEORIGIN;
|
|
||||||
add_header X-Content-Type-Options nosniff;
|
|
||||||
add_header X-XSS-Protection "1; mode=block";
|
|
||||||
|
|
||||||
location / {
|
|
||||||
proxy_pass http://localhost:8443/;
|
|
||||||
proxy_set_header Accept-Encoding gzip;
|
|
||||||
proxy_set_header Connection upgrade;
|
|
||||||
proxy_set_header Upgrade $http_upgrade;
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# HTTPS configuration. Scores an A on SSL Labs' SSL Server Test.
|
|
||||||
server {
|
|
||||||
listen 443 ssl http2;
|
|
||||||
listen [::]:443 ssl http2;
|
|
||||||
server_name code.example.com code.example.org;
|
|
||||||
|
|
||||||
# If you're using CloudFlare, uncomment the following line.
|
|
||||||
# real_ip_header CF-Connecting-IP;
|
|
||||||
|
|
||||||
# SSL certificate and key.
|
|
||||||
ssl_certificate /path/to/cert.pem;
|
|
||||||
ssl_certificate_key /path/to/cert-key.pem;
|
|
||||||
|
|
||||||
# Strong TLS configuration. Originally taken from https://cipherli.st/.
|
|
||||||
ssl_protocols TLSv1.2 TLSv1.3;
|
|
||||||
ssl_prefer_server_ciphers on;
|
|
||||||
# ssl_dhparam /etc/nginx/dhparam.pem; # openssl dhparam -out /etc/nginx/dhparam.pem 4096
|
|
||||||
ssl_ciphers EECDH+AESGCM:EDH+AESGCM;
|
|
||||||
ssl_ecdh_curve secp384r1;
|
|
||||||
ssl_session_timeout 10m;
|
|
||||||
ssl_session_cache shared:SSL:10m;
|
|
||||||
ssl_session_tickets off;
|
|
||||||
ssl_stapling on;
|
|
||||||
ssl_stapling_verify on;
|
|
||||||
resolver 8.8.8.8 8.8.4.4 valid=300s;
|
|
||||||
resolver_timeout 5s;
|
|
||||||
|
|
||||||
# Other security options.
|
|
||||||
# add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload";
|
|
||||||
add_header X-Frame-Options DENY;
|
|
||||||
add_header X-Content-Type-Options nosniff;
|
|
||||||
add_header X-XSS-Protection "1; mode=block";
|
|
||||||
|
|
||||||
location / {
|
|
||||||
proxy_pass http://localhost:8443/;
|
|
||||||
proxy_set_header Accept-Encoding gzip;
|
|
||||||
proxy_set_header Connection upgrade;
|
|
||||||
proxy_set_header Upgrade $http_upgrade;
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Make sure to set the `proxy_pass` directive to the actual address of your
|
|
||||||
code-server instance and the `server_name` directive to the hostname/s of your
|
|
||||||
website. If you're using an SSL certificate, make sure to change the
|
|
||||||
`ssl_certificate` and `ssl_certificate_key` directives. If not, remove the HTTPS
|
|
||||||
`server` block entirely.
|
|
||||||
|
|
||||||
[nginx-install]: https://docs.nginx.com/nginx/admin-guide/installing-nginx/installing-nginx-open-source/#installing-a-prebuilt-package
|
|
||||||
|
|
||||||
|
|
||||||
### Apache Reverse Proxy
|
|
||||||
|
|
||||||
The following virtual host configuration file works with code-server. When
|
|
||||||
starting code-server, be sure to provide the `--allow-http` and `--trust-proxy`
|
|
||||||
flags so Apache can connect to code-server properly.
|
|
||||||
|
|
||||||
Some of these directives require a version of Apache greater than or equal to
|
|
||||||
`2.4.0`, which might not be available in your distro's repositories. You will
|
|
||||||
also need to enable the following modules: `rewrite`, `proxy`, `proxy_http`,
|
|
||||||
`proxy_wstunnel`, `ssl`, and `socache_shmcb`.
|
|
||||||
|
|
||||||
```
|
|
||||||
# HTTP configuration.
|
|
||||||
<VirtualHost *:80>
|
|
||||||
ServerName code.example.com
|
|
||||||
|
|
||||||
# If you're using CloudFlare, uncomment the following line.
|
|
||||||
# RemoteIPHeader CF-Connecting-IP;
|
|
||||||
|
|
||||||
# Other security options.
|
|
||||||
Header always set X-Frame-Options DENY
|
|
||||||
Header always set X-Content-Type-Options nosniff
|
|
||||||
|
|
||||||
RewriteEngine On
|
|
||||||
RewriteCond %{HTTP:Upgrade} websocket [NC]
|
|
||||||
RewriteCond %{HTTP:Connection} upgrade [NC]
|
|
||||||
RewriteRule .* "ws://localhost:8443%{REQUEST_URI}" [P]
|
|
||||||
|
|
||||||
RequestHeader set X-Forwarded-Proto https
|
|
||||||
RequestHeader set X-Forwarded-Port 443
|
|
||||||
|
|
||||||
ProxyRequests off
|
|
||||||
ProxyPass / http://localhost:8443/ nocanon
|
|
||||||
ProxyPassReverse / http://localhost:8443/
|
|
||||||
</VirtualHost>
|
|
||||||
|
|
||||||
# HTTPS configuration. Scores an A on SSL Labs' SSL Server Test.
|
|
||||||
<IfModule mod_ssl.c>
|
|
||||||
SSLStaplingCache shmcb:/tmp/stapling_cache(150000)
|
|
||||||
<VirtualHost *:443>
|
|
||||||
ServerName code.example.com
|
|
||||||
|
|
||||||
# If you're using CloudFlare, uncomment the following line.
|
|
||||||
# RemoteIPHeader CF-Connecting-IP;
|
|
||||||
|
|
||||||
# SSL certificate and key.
|
|
||||||
SSLEngine On
|
|
||||||
SSLCertificateFile /path/to/cert.pem
|
|
||||||
SSLCertifcateKeyFile /path/to/cert-key.pem
|
|
||||||
SSLCertificateChainFile /path/to/chain.pem
|
|
||||||
|
|
||||||
# Strong TLS configuration. Originally taken from https://cipherli.st/.
|
|
||||||
SSLCipherSuite EECDH+AESGCM:EDH+AESGCM
|
|
||||||
SSLProtocol -all +TLSv1.2
|
|
||||||
SSLHonorCipherOrder On
|
|
||||||
SSLCompression off
|
|
||||||
SSLUseStapling on
|
|
||||||
SSLStaplingCache "shmcb:logs/stapling-cache(150000)"
|
|
||||||
SSLSessionTickets Off
|
|
||||||
|
|
||||||
# Other security options.
|
|
||||||
# Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
|
|
||||||
Header always set X-Frame-Options DENY
|
|
||||||
Header always set X-Content-Type-Options nosniff
|
|
||||||
|
|
||||||
RewriteEngine On
|
|
||||||
RewriteCond %{HTTP:Upgrade} websocket [NC]
|
|
||||||
RewriteCond %{HTTP:Connection} upgrade [NC]
|
|
||||||
RewriteRule .* "ws://localhost:8443%{REQUEST_URI}" [P]
|
|
||||||
|
|
||||||
RequestHeader set X-Forwarded-Proto https
|
|
||||||
RequestHeader set X-Forwarded-Port 443
|
|
||||||
|
|
||||||
ProxyRequests off
|
|
||||||
ProxyPass / http://localhost:8443/ nocanon
|
|
||||||
ProxyPassReverse / http://localhost:8443/
|
|
||||||
</VirtualHost>
|
|
||||||
</IfModule>
|
|
||||||
```
|
|
||||||
|
|
||||||
Make sure to set the `ProxyPass`, `ProxyPassReverse` and `RewriteRule`
|
|
||||||
directives to the actual address of your code-server instance and the
|
|
||||||
`ServerName` directive to the hostname of your website. If you're using SSL,
|
|
||||||
make sure to change the `SSLCertificateFile`, `SSLCertificateKeyFile`, and
|
|
||||||
`SSLCertificateChainFile` directives. If not, remove the HTTPS `IfModule` block
|
|
||||||
entirely.
|
|
||||||
|
|
||||||
For more details about Apache reverse proxy configuration, check out the
|
|
||||||
[mod_proxy documentation](apache-mod_proxy).
|
|
||||||
|
|
||||||
[apache-mod_proxy]: https://httpd.apache.org/docs/current/mod/mod_proxy.html
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
// Once our entry file is loaded we no longer need nbin to bypass normal Node
|
||||||
|
// execution. We can still shim the fs into the binary even when bypassing. This
|
||||||
|
// will ensure for example that a spawn like `${process.argv[0]} -e` will work
|
||||||
|
// while still allowing us to access files within the binary.
|
||||||
|
process.env.NBIN_BYPASS = true;
|
||||||
|
|
||||||
|
require("../../bootstrap-amd").load("vs/server/src/cli");
|
82
package.json
|
@ -1,70 +1,34 @@
|
||||||
{
|
{
|
||||||
"name": "@coder/code-server",
|
|
||||||
"repository": "https://github.com/cdr/code-server",
|
|
||||||
"author": "Coder",
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"description": "Run VS Code remotely.",
|
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build:rules": "cd ./rules && tsc -p .",
|
"ensure-in-vscode": "bash ./scripts/tasks.bash ensure-in-vscode",
|
||||||
"packages:install": "cd ./packages && yarn",
|
"preinstall": "yarn ensure-in-vscode && cd ../../../ && yarn || true",
|
||||||
"postinstall": "npm-run-all --parallel packages:install build:rules",
|
"postinstall": "rm -rf node_modules/@types/node",
|
||||||
"start": "cd ./packages/server && yarn start",
|
"start": "yarn ensure-in-vscode && nodemon --watch ../../../out --verbose ../../../out/vs/server/main.js",
|
||||||
"task": "ts-node -r tsconfig-paths/register build/tasks.ts",
|
"watch": "yarn ensure-in-vscode && cd ../../../ && yarn watch",
|
||||||
"test": "cd ./packages && yarn test"
|
"build": "bash ./scripts/tasks.bash build",
|
||||||
|
"package": "bash ./scripts/tasks.bash package",
|
||||||
|
"package-prebuilt": "bash ./scripts/tasks.bash package-prebuilt",
|
||||||
|
"binary": "bash ./scripts/tasks.bash binary",
|
||||||
|
"patch:generate": "yarn ensure-in-vscode && cd ../../../ && git diff --staged > ./src/vs/server/scripts/vscode.patch",
|
||||||
|
"patch:apply": "yarn ensure-in-vscode && cd ../../../ && git apply ./src/vs/server/scripts/vscode.patch"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/fs-extra": "^5.0.4",
|
"@coder/nbin": "^1.2.0",
|
||||||
"@types/node": "^10.12.18",
|
"@types/pem": "^1.9.5",
|
||||||
"@types/tar": "^4.0.0",
|
"@types/safe-compare": "^1.1.0",
|
||||||
"@types/trash": "^4.3.1",
|
"@types/tar-stream": "^1.6.1",
|
||||||
"cache-loader": "^2.0.1",
|
"nodemon": "^1.19.1"
|
||||||
"cross-env": "^5.2.0",
|
|
||||||
"crypto-browserify": "^3.12.0",
|
|
||||||
"css-loader": "^2.1.0",
|
|
||||||
"file-loader": "^3.0.1",
|
|
||||||
"fork-ts-checker-webpack-plugin": "^0.5.2",
|
|
||||||
"fs-extra": "^7.0.1",
|
|
||||||
"happypack": "^5.0.1",
|
|
||||||
"html-webpack-plugin": "^3.2.0",
|
|
||||||
"http-browserify": "^1.7.0",
|
|
||||||
"ignore-loader": "^0.1.2",
|
|
||||||
"mini-css-extract-plugin": "^0.5.0",
|
|
||||||
"node-sass": "^4.11.0",
|
|
||||||
"npm-run-all": "^4.1.5",
|
|
||||||
"path-browserify": "^1.0.0",
|
|
||||||
"preload-webpack-plugin": "^3.0.0-beta.2",
|
|
||||||
"sass-loader": "^7.1.0",
|
|
||||||
"string-replace-loader": "^2.1.1",
|
|
||||||
"style-loader": "^0.23.1",
|
|
||||||
"tar": "^4.4.8",
|
|
||||||
"terser-webpack-plugin": "^1.2.3",
|
|
||||||
"ts-loader": "^5.3.3",
|
|
||||||
"ts-node": "^7.0.1",
|
|
||||||
"tsconfig-paths": "^3.8.0",
|
|
||||||
"tslib": "^1.9.3",
|
|
||||||
"tslint": "^5.12.1",
|
|
||||||
"typescript": "^3.2.2",
|
|
||||||
"typescript-tslint-plugin": "^0.2.1",
|
|
||||||
"uglifyjs-webpack-plugin": "^2.1.1",
|
|
||||||
"url-loader": "^1.1.2",
|
|
||||||
"util": "^0.11.1",
|
|
||||||
"webpack": "^4.28.4",
|
|
||||||
"webpack-bundle-analyzer": "^3.0.3",
|
|
||||||
"webpack-cli": "^3.2.1",
|
|
||||||
"webpack-dev-middleware": "^3.5.0",
|
|
||||||
"webpack-dev-server": "^3.1.14",
|
|
||||||
"webpack-hot-middleware": "^2.24.3",
|
|
||||||
"webpack-pwa-manifest": "^4.0.0",
|
|
||||||
"workbox-webpack-plugin": "^4.1.0",
|
|
||||||
"write-file-webpack-plugin": "^4.5.0"
|
|
||||||
},
|
},
|
||||||
"resolutions": {
|
"resolutions": {
|
||||||
"bindings": "1.3.0"
|
"@types/node": "^10.12.12",
|
||||||
|
"safe-buffer": "^5.1.1"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"node-loader": "^0.6.0",
|
"@coder/logger": "^1.1.8",
|
||||||
"node-pty": "0.8.1",
|
"httpolyglot": "^0.1.2",
|
||||||
"spdlog": "0.8.1",
|
"pem": "^1.14.2",
|
||||||
"webpack-merge": "^4.2.1"
|
"safe-compare": "^1.1.4",
|
||||||
|
"tar-stream": "^2.1.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +0,0 @@
|
||||||
{
|
|
||||||
"name": "@coder/app",
|
|
||||||
"scripts": {
|
|
||||||
"start": "node ../../../node_modules/webpack-dev-server/bin/webpack-dev-server.js --config ./webpack.config.js",
|
|
||||||
"build": "node ../../../node_modules/webpack/bin/webpack.js --config ./webpack.config.js"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"@material/checkbox": "^0.44.1",
|
|
||||||
"@material/textfield": "^0.44.1",
|
|
||||||
"material-components-web": "^0.44.0"
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,30 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
|
|
||||||
<head>
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1">
|
|
||||||
<title>Authenticate: code-server</title>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<form id="login-form">
|
|
||||||
<div class="login">
|
|
||||||
<div class="back">
|
|
||||||
<- Back </div> <h4 class="title">code-server</h4>
|
|
||||||
<h2 class="subtitle">
|
|
||||||
Enter server password
|
|
||||||
</h2>
|
|
||||||
<div class="mdc-text-field">
|
|
||||||
<input type="password" id="password" class="mdc-text-field__input" required>
|
|
||||||
<label class="mdc-floating-label" for="password">Password</label>
|
|
||||||
<div class="mdc-line-ripple"></div>
|
|
||||||
</div>
|
|
||||||
<button id="submit" class="mdc-button mdc-button--unelevated">
|
|
||||||
<span class="mdc-button__label">Enter IDE</span>
|
|
||||||
</button>
|
|
||||||
<div id="error-display"></div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
|
@ -1,121 +0,0 @@
|
||||||
@import url("https://use.typekit.net/vzk7ygg.css");
|
|
||||||
|
|
||||||
html, body {
|
|
||||||
background-color: #FFFFFF;
|
|
||||||
min-height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
|
||||||
font-family: 'aktiv-grotesk';
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
height: calc(100vh - 20px);
|
|
||||||
margin: 0;
|
|
||||||
padding: 10px;
|
|
||||||
--mdc-theme-primary: #AAADA1;
|
|
||||||
--mdc-theme-secondary: #AAADA1;
|
|
||||||
|
|
||||||
&.in-app {
|
|
||||||
.back {
|
|
||||||
pointer-events: all;
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.login {
|
|
||||||
box-shadow: 0 18px 80px 10px rgba(69, 65, 78, 0.08);
|
|
||||||
max-width: 328px;
|
|
||||||
width: 100%;
|
|
||||||
padding: 40px;
|
|
||||||
border-radius: 5px;
|
|
||||||
position: relative;
|
|
||||||
color: #575962;
|
|
||||||
|
|
||||||
.title {
|
|
||||||
margin-bottom: 0px;
|
|
||||||
font-size: 12px;
|
|
||||||
font-weight: 500;
|
|
||||||
letter-spacing: 1.5px;
|
|
||||||
line-height: 15px;
|
|
||||||
margin-bottom: 5px;
|
|
||||||
margin-top: 0px;
|
|
||||||
text-align: center;
|
|
||||||
text-transform: uppercase;
|
|
||||||
}
|
|
||||||
|
|
||||||
.subtitle {
|
|
||||||
text-align: center;
|
|
||||||
margin: 0;
|
|
||||||
font-size: 19px;
|
|
||||||
font-weight: bold;
|
|
||||||
line-height: 25px;
|
|
||||||
margin-bottom: 45px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mdc-text-field {
|
|
||||||
width: 100%;
|
|
||||||
background: none !important;
|
|
||||||
|
|
||||||
&::before {
|
|
||||||
background: none !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.mdc-form-field {
|
|
||||||
text-align: left;
|
|
||||||
font-size: 12px;
|
|
||||||
color: #797E84;
|
|
||||||
margin-top: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mdc-button {
|
|
||||||
border-radius: 24px;
|
|
||||||
padding-left: 75px;
|
|
||||||
padding-right: 75px;
|
|
||||||
padding-top: 15px;
|
|
||||||
padding-bottom: 15px;
|
|
||||||
height: 48px;
|
|
||||||
margin: 0 auto;
|
|
||||||
display: block;
|
|
||||||
box-shadow: 0 12px 17px 2px rgba(171,173,163,0.14), 0 5px 22px 4px rgba(171,173,163,0.12), 0 7px 8px -4px rgba(171,173,163,0.2);
|
|
||||||
margin-top: 40px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.mdc-text-field--focused:not(.mdc-text-field--disabled) .mdc-floating-label {
|
|
||||||
color: var(--mdc-theme-primary);
|
|
||||||
}
|
|
||||||
|
|
||||||
.mdc-floating-label--float-above {
|
|
||||||
transform: translateY(-70%) scale(0.75);
|
|
||||||
}
|
|
||||||
|
|
||||||
.mdc-text-field:not(.mdc-text-field--disabled):not(.mdc-text-field--outlined):not(.mdc-text-field--textarea) .mdc-text-field__input, .mdc-text-field:not(.mdc-text-field--disabled):not(.mdc-text-field--outlined):not(.mdc-text-field--textarea) .mdc-text-field__input:hover {
|
|
||||||
border-bottom-color: #EBEDF2;
|
|
||||||
}
|
|
||||||
|
|
||||||
.back {
|
|
||||||
position: absolute;
|
|
||||||
top: -50px;
|
|
||||||
left: -50px;
|
|
||||||
font-weight: bold;
|
|
||||||
opacity: 0;
|
|
||||||
pointer-events: none;
|
|
||||||
|
|
||||||
// transition: 500ms opacity ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
#error-display {
|
|
||||||
box-sizing: border-box;
|
|
||||||
color: #bb2d0f;
|
|
||||||
font-size: 14px;
|
|
||||||
font-weight: 400;
|
|
||||||
letter-spacing: 0.3px;
|
|
||||||
line-height: 12px;
|
|
||||||
padding: 8px;
|
|
||||||
padding-bottom: 0;
|
|
||||||
padding-top: 20px;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
|
@ -1,46 +0,0 @@
|
||||||
//@ts-ignore
|
|
||||||
import { MDCTextField } from "@material/textfield";
|
|
||||||
//@ts-ignore
|
|
||||||
import { MDCCheckbox } from "@material/checkbox";
|
|
||||||
import "material-components-web/dist/material-components-web.css";
|
|
||||||
import "./app.scss";
|
|
||||||
|
|
||||||
document.querySelectorAll(".mdc-text-field").forEach((d) => new MDCTextField(d));
|
|
||||||
document.querySelectorAll(".mdc-checkbox").forEach((d) => new MDCCheckbox(d));
|
|
||||||
|
|
||||||
window.addEventListener("message", (event) => {
|
|
||||||
if (event.data === "app") {
|
|
||||||
document.body.classList.add("in-app");
|
|
||||||
|
|
||||||
const back = document.querySelector(".back")!;
|
|
||||||
back.addEventListener("click", () => {
|
|
||||||
(event.source as Window).postMessage("back", event.origin);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const password = document.getElementById("password") as HTMLInputElement;
|
|
||||||
const form = document.getElementById("login-form") as HTMLFormElement;
|
|
||||||
|
|
||||||
if (!form) {
|
|
||||||
throw new Error("No password form found");
|
|
||||||
}
|
|
||||||
|
|
||||||
form.addEventListener("submit", (e) => {
|
|
||||||
e.preventDefault();
|
|
||||||
document.cookie = `password=${password.value}; `
|
|
||||||
+ `path=${location.pathname.replace(/\/login\/?$/, "/")}; `
|
|
||||||
+ `domain=${location.hostname}`;
|
|
||||||
location.reload();
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Notify user on load of page if previous password was unsuccessful
|
|
||||||
*/
|
|
||||||
const reg = new RegExp(`password=(\\w+);?`);
|
|
||||||
const matches = document.cookie.match(reg);
|
|
||||||
const errorDisplay = document.getElementById("error-display") as HTMLDivElement;
|
|
||||||
|
|
||||||
if (document.referrer === document.location.href && matches) {
|
|
||||||
errorDisplay.innerText = "Password is incorrect!";
|
|
||||||
}
|
|
|
@ -1,16 +0,0 @@
|
||||||
const path = require("path");
|
|
||||||
const webpack = require("webpack");
|
|
||||||
const merge = require("webpack-merge");
|
|
||||||
const HtmlWebpackPlugin = require("html-webpack-plugin");
|
|
||||||
|
|
||||||
const root = path.resolve(__dirname, "../../..");
|
|
||||||
|
|
||||||
module.exports = merge(
|
|
||||||
require(path.join(root, "scripts/webpack.client.config.js"))({
|
|
||||||
dirname: __dirname,
|
|
||||||
entry: path.join(__dirname, "src/app.ts"),
|
|
||||||
name: "login",
|
|
||||||
template: path.join(__dirname, "src/app.html"),
|
|
||||||
}), {
|
|
||||||
},
|
|
||||||
);
|
|
|
@ -1,606 +0,0 @@
|
||||||
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
|
|
||||||
# yarn lockfile v1
|
|
||||||
|
|
||||||
|
|
||||||
"@material/animation@^0.41.0":
|
|
||||||
version "0.41.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/animation/-/animation-0.41.0.tgz#315b45b32e1aeebee8a4cf555b8ad52076d09ddd"
|
|
||||||
integrity sha512-yYAwJbX3Q2AFd4dr6IYOsWLQy2HN8zWOFVl9AbUXunjzTfJCa/ecfXCriaT6qkmoNoHeTdJHRrsQJZC5GsPvzA==
|
|
||||||
|
|
||||||
"@material/auto-init@^0.41.0":
|
|
||||||
version "0.41.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/auto-init/-/auto-init-0.41.0.tgz#8a59bb0b83e0f51ead9508074f9a29b2b6a20eec"
|
|
||||||
integrity sha512-jp6L8MpYu7DudgDfA8iTyD9BwQrYPEDsIJGbqzN9vcCBl5FoBatkB8pcFXKr+1mRBk7T1Qmf6+H5nDtxyXjHEQ==
|
|
||||||
|
|
||||||
"@material/base@^0.41.0":
|
|
||||||
version "0.41.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/base/-/base-0.41.0.tgz#badadce711b4c25b1eb889a5e7581e32cd07c421"
|
|
||||||
integrity sha512-tEyzwBRu3d1H120SfKsDVYZHcqT5lKohh/7cWKR93aAaPDkSvjpKJIjyu2yuSkjpDduVZGzVocYbOvhUKhhzXQ==
|
|
||||||
|
|
||||||
"@material/button@^0.44.0":
|
|
||||||
version "0.44.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/button/-/button-0.44.0.tgz#f01dcbea88bdc314e7640b76e5558101c8b4d69d"
|
|
||||||
integrity sha512-T8u8s8rlB49D9/5Nh5b0XsKRgSq3X0yWGo71MgaTnCnwxt8oZ6PxW/cH6Nn3Xp0NCr3mlSVQs08BviUfAmtlsg==
|
|
||||||
dependencies:
|
|
||||||
"@material/elevation" "^0.44.0"
|
|
||||||
"@material/feature-targeting" "^0.44.0"
|
|
||||||
"@material/ripple" "^0.44.0"
|
|
||||||
"@material/rtl" "^0.42.0"
|
|
||||||
"@material/shape" "^0.43.0"
|
|
||||||
"@material/theme" "^0.43.0"
|
|
||||||
"@material/typography" "^0.44.0"
|
|
||||||
|
|
||||||
"@material/card@^0.44.0":
|
|
||||||
version "0.44.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/card/-/card-0.44.0.tgz#e62050e3e77f525173a015119200055cd7b71bf0"
|
|
||||||
integrity sha512-fUixXuh133bVp5c1gPIHreL5jwMJEeVIQf0E4xdxhkA+i4ku8fIAvIW62EuCmfJsXicv4q8NG3Ip6pCY+NW3ZA==
|
|
||||||
dependencies:
|
|
||||||
"@material/elevation" "^0.44.0"
|
|
||||||
"@material/ripple" "^0.44.0"
|
|
||||||
"@material/rtl" "^0.42.0"
|
|
||||||
"@material/shape" "^0.43.0"
|
|
||||||
"@material/theme" "^0.43.0"
|
|
||||||
|
|
||||||
"@material/checkbox@^0.44.0":
|
|
||||||
version "0.44.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/checkbox/-/checkbox-0.44.0.tgz#5d0eee1db006db9f0fb700bf1c20408292305cf7"
|
|
||||||
integrity sha512-IzucxG+NuPNyByGmHg/cuYJ5ooMKouuj994PZXZyqb7owfrjjtXm7wjav66cvCowbVbcoa1owQMGBi18C9f4TQ==
|
|
||||||
dependencies:
|
|
||||||
"@material/animation" "^0.41.0"
|
|
||||||
"@material/base" "^0.41.0"
|
|
||||||
"@material/ripple" "^0.44.0"
|
|
||||||
"@material/rtl" "^0.42.0"
|
|
||||||
"@material/selection-control" "^0.44.0"
|
|
||||||
"@material/theme" "^0.43.0"
|
|
||||||
|
|
||||||
"@material/checkbox@^0.44.1":
|
|
||||||
version "0.44.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/checkbox/-/checkbox-0.44.1.tgz#7e69271ccab7c57914a475da3a15d4d36702c1c4"
|
|
||||||
integrity sha512-RFUNc+9RKRozL+gXfJ8V57tXfC31Q9R9tRMTHpe62NXZriTrwNJDnSkFIERDXqtMGtkKUnIlPfPE5znF6XyPUw==
|
|
||||||
dependencies:
|
|
||||||
"@material/animation" "^0.41.0"
|
|
||||||
"@material/base" "^0.41.0"
|
|
||||||
"@material/feature-targeting" "^0.44.1"
|
|
||||||
"@material/ripple" "^0.44.1"
|
|
||||||
"@material/rtl" "^0.42.0"
|
|
||||||
"@material/selection-control" "^0.44.1"
|
|
||||||
"@material/theme" "^0.43.0"
|
|
||||||
|
|
||||||
"@material/chips@^0.44.0":
|
|
||||||
version "0.44.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/chips/-/chips-0.44.0.tgz#bf553a5bf5db7320978402ac92069c9688b84d5a"
|
|
||||||
integrity sha512-+qrme6sGwYmX/ixHAo3Z1M7lorsxRyKexn1l+BSBX5PBc2f4w5Ml1eYYYcyVGfLX9LXmefRk0G6dUXXPyCE00g==
|
|
||||||
dependencies:
|
|
||||||
"@material/animation" "^0.41.0"
|
|
||||||
"@material/base" "^0.41.0"
|
|
||||||
"@material/checkbox" "^0.44.0"
|
|
||||||
"@material/elevation" "^0.44.0"
|
|
||||||
"@material/ripple" "^0.44.0"
|
|
||||||
"@material/shape" "^0.43.0"
|
|
||||||
"@material/theme" "^0.43.0"
|
|
||||||
"@material/typography" "^0.44.0"
|
|
||||||
|
|
||||||
"@material/dialog@^0.44.0":
|
|
||||||
version "0.44.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/dialog/-/dialog-0.44.0.tgz#388f93f9f225824c75cbe9da8c464a52d79972e8"
|
|
||||||
integrity sha512-V6ButfknOMKOscL0Y39yLjamxvrIuyugobjf5s44ZeJc+9jUSkC7M3zP+T7rh358NcX+JSPP8iCGmUn/+LXpMQ==
|
|
||||||
dependencies:
|
|
||||||
"@material/animation" "^0.41.0"
|
|
||||||
"@material/base" "^0.41.0"
|
|
||||||
"@material/dom" "^0.41.0"
|
|
||||||
"@material/elevation" "^0.44.0"
|
|
||||||
"@material/ripple" "^0.44.0"
|
|
||||||
"@material/rtl" "^0.42.0"
|
|
||||||
"@material/shape" "^0.43.0"
|
|
||||||
"@material/theme" "^0.43.0"
|
|
||||||
"@material/typography" "^0.44.0"
|
|
||||||
focus-trap "^4.0.2"
|
|
||||||
|
|
||||||
"@material/dom@^0.41.0":
|
|
||||||
version "0.41.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/dom/-/dom-0.41.0.tgz#6756865f97bad4c91ee75e69d769d7cdc25398ae"
|
|
||||||
integrity sha512-wOJrMwjPddYXpQFZAIaCLWI3TO/6KU1lxESTBzunni8A4FHQVWhokml5Xt85GqZwmPFeIF2s+D0wfbWyrGBuKQ==
|
|
||||||
|
|
||||||
"@material/drawer@^0.44.0":
|
|
||||||
version "0.44.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/drawer/-/drawer-0.44.0.tgz#74b3ddfb741bffc72331c7a73cf62716fd3f0ab3"
|
|
||||||
integrity sha512-AYwFe0jgqqSmJd1bny8JJTA2SScF86Wfbk99lXXEwd/acS8IbnnuH6zfAg6MyJX12FDb8dE8Z/Ok1IwLiVa9sQ==
|
|
||||||
dependencies:
|
|
||||||
"@material/animation" "^0.41.0"
|
|
||||||
"@material/base" "^0.41.0"
|
|
||||||
"@material/elevation" "^0.44.0"
|
|
||||||
"@material/list" "^0.44.0"
|
|
||||||
"@material/ripple" "^0.44.0"
|
|
||||||
"@material/rtl" "^0.42.0"
|
|
||||||
"@material/shape" "^0.43.0"
|
|
||||||
"@material/theme" "^0.43.0"
|
|
||||||
"@material/typography" "^0.44.0"
|
|
||||||
focus-trap "^4.0.2"
|
|
||||||
|
|
||||||
"@material/elevation@^0.44.0":
|
|
||||||
version "0.44.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/elevation/-/elevation-0.44.0.tgz#ca16a67188ce9810dc2fa3d7a39073e72df4b754"
|
|
||||||
integrity sha512-edNou34yFCSMb6XXe/6Y7AEh8DigWAhBUyIeMiMBD4k1km2xYCJbcnl8FBPJFteOrca97KoJComRlJPB6EurRQ==
|
|
||||||
dependencies:
|
|
||||||
"@material/animation" "^0.41.0"
|
|
||||||
"@material/theme" "^0.43.0"
|
|
||||||
|
|
||||||
"@material/fab@^0.44.0":
|
|
||||||
version "0.44.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/fab/-/fab-0.44.0.tgz#0bcbbdfb6f24c53d59e08c9c0d400d2616dea184"
|
|
||||||
integrity sha512-1CEP4NlXDYioJ/YpSjh/MlIygtoC7CaHqIbucxX1O5WRPmS7K1uPt+o7netbLErAmcJdV/JrI/tqh9kKuX2x/Q==
|
|
||||||
dependencies:
|
|
||||||
"@material/animation" "^0.41.0"
|
|
||||||
"@material/elevation" "^0.44.0"
|
|
||||||
"@material/ripple" "^0.44.0"
|
|
||||||
"@material/rtl" "^0.42.0"
|
|
||||||
"@material/shape" "^0.43.0"
|
|
||||||
"@material/theme" "^0.43.0"
|
|
||||||
"@material/typography" "^0.44.0"
|
|
||||||
|
|
||||||
"@material/feature-targeting@^0.44.0":
|
|
||||||
version "0.44.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/feature-targeting/-/feature-targeting-0.44.0.tgz#52cc73f0c8a83159de0357aebe74f15f9856fb4c"
|
|
||||||
integrity sha512-ShuC2TOLfjFpYUCQFtvkqDJhM6HTaucSx5HkRbOvOG+VlpzDx6pAqRUmdVaq2p7tHoQf2vwPMlSVm3gOjWt4VQ==
|
|
||||||
|
|
||||||
"@material/feature-targeting@^0.44.1":
|
|
||||||
version "0.44.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/feature-targeting/-/feature-targeting-0.44.1.tgz#afafc80294e5efab94bee31a187273d43d34979a"
|
|
||||||
integrity sha512-90cc7njn4aHbH9UxY8qgZth1W5JgOgcEdWdubH1t7sFkwqFxS5g3zgxSBt46TygFBVIXNZNq35Xmg80wgqO7Pg==
|
|
||||||
|
|
||||||
"@material/floating-label@^0.44.0":
|
|
||||||
version "0.44.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/floating-label/-/floating-label-0.44.0.tgz#8694cd49f6905641b67a9e7a112b820d028f09c7"
|
|
||||||
integrity sha512-k4npGNxyMtnjgJZNjU5VvqqaUqlbzlbVAhepT8PxYTpj+4Skg6PjHwieTCDCgsbqHvFcQX+WfUrSZXY7wFV7cw==
|
|
||||||
dependencies:
|
|
||||||
"@material/animation" "^0.41.0"
|
|
||||||
"@material/base" "^0.41.0"
|
|
||||||
"@material/rtl" "^0.42.0"
|
|
||||||
"@material/theme" "^0.43.0"
|
|
||||||
"@material/typography" "^0.44.0"
|
|
||||||
|
|
||||||
"@material/floating-label@^0.44.1":
|
|
||||||
version "0.44.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/floating-label/-/floating-label-0.44.1.tgz#39af84a3a0abbfa6d210911d5f4200a65c2ef59b"
|
|
||||||
integrity sha512-umj5q5feJcZuB8snRX5aVBrwQNnrt/HcvN7pENzgqaYZNcmBnxRl0OutTlHCn6l7OVU9VlWhFMf77DYwmMWKJQ==
|
|
||||||
dependencies:
|
|
||||||
"@material/animation" "^0.41.0"
|
|
||||||
"@material/base" "^0.41.0"
|
|
||||||
"@material/rtl" "^0.42.0"
|
|
||||||
"@material/theme" "^0.43.0"
|
|
||||||
"@material/typography" "^0.44.1"
|
|
||||||
|
|
||||||
"@material/form-field@^0.44.0":
|
|
||||||
version "0.44.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/form-field/-/form-field-0.44.0.tgz#b7518e885c0e953a2a5fe0140af927c30e066f4e"
|
|
||||||
integrity sha512-SK+V34dzoBCQ/CHn5nBp8BAh21Vj9p1pcok+/WpYBTeg4EphTYP2nUQLMNEN92l6zjgAYf+g9Ocj3t26HNHWqA==
|
|
||||||
dependencies:
|
|
||||||
"@material/base" "^0.41.0"
|
|
||||||
"@material/rtl" "^0.42.0"
|
|
||||||
"@material/selection-control" "^0.44.0"
|
|
||||||
"@material/theme" "^0.43.0"
|
|
||||||
"@material/typography" "^0.44.0"
|
|
||||||
|
|
||||||
"@material/grid-list@^0.44.0":
|
|
||||||
version "0.44.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/grid-list/-/grid-list-0.44.0.tgz#bd31d992ab1a910731e4a47c11fe91d44e3bc02b"
|
|
||||||
integrity sha512-NxLL0A48K1O14ZZymFIyf6HDbF33+NgXYXqP2yosTC3Jw4iwmUcJTpFTmSw1U/m1xT4zEpeKEGJ4vjVUWpS9Mg==
|
|
||||||
dependencies:
|
|
||||||
"@material/base" "^0.41.0"
|
|
||||||
"@material/rtl" "^0.42.0"
|
|
||||||
"@material/theme" "^0.43.0"
|
|
||||||
"@material/typography" "^0.44.0"
|
|
||||||
|
|
||||||
"@material/icon-button@^0.44.0":
|
|
||||||
version "0.44.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/icon-button/-/icon-button-0.44.0.tgz#febbcfd27d91eca8096ae042b9c07ed0f65345e9"
|
|
||||||
integrity sha512-n6L7RaRyEci6eGsuBTSEG+t9ATHAHaMlf9zuTWorEnIXY4DAmGO7ggBjw4+1XIOjhpLeIjyJdcvUK6Yz/UVM6Q==
|
|
||||||
dependencies:
|
|
||||||
"@material/base" "^0.41.0"
|
|
||||||
"@material/ripple" "^0.44.0"
|
|
||||||
"@material/theme" "^0.43.0"
|
|
||||||
|
|
||||||
"@material/icon-toggle@^0.44.0":
|
|
||||||
version "0.44.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/icon-toggle/-/icon-toggle-0.44.0.tgz#b9de32f194b5aa9721ca799d59be0f477a5c5305"
|
|
||||||
integrity sha512-8T1b4iK61/q/3U0iIjEDJ9do5viCQ45IbrQqa8EYCZ1KDU/Q8z5N+bvOzQK8XnTL51BdDRMgP9lfQZh6nszmkA==
|
|
||||||
dependencies:
|
|
||||||
"@material/animation" "^0.41.0"
|
|
||||||
"@material/base" "^0.41.0"
|
|
||||||
"@material/ripple" "^0.44.0"
|
|
||||||
"@material/theme" "^0.43.0"
|
|
||||||
|
|
||||||
"@material/image-list@^0.44.0":
|
|
||||||
version "0.44.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/image-list/-/image-list-0.44.0.tgz#a27996962044ac8c9ce6cb509f63746f08ed2e98"
|
|
||||||
integrity sha512-kI9aKJdc1Bd02l8nRTGG1wy/lNkECScfnBmCiLQ3XjAFtRYd2eWO0Z/AVvUG3egsIZnZBxqFGGsf5Htm9E/HiQ==
|
|
||||||
dependencies:
|
|
||||||
"@material/shape" "^0.43.0"
|
|
||||||
"@material/theme" "^0.43.0"
|
|
||||||
"@material/typography" "^0.44.0"
|
|
||||||
|
|
||||||
"@material/layout-grid@^0.41.0":
|
|
||||||
version "0.41.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/layout-grid/-/layout-grid-0.41.0.tgz#2e7d3be76313e0684d573b10c2c6a88b3230d251"
|
|
||||||
integrity sha512-Sa5RNoTGgfIojqJ9E94p7/k11V6q/tGk7HwKi4AQNAPjxield0zcl3G/SbsSb8YSHoK+D+7OXDN+n11x6EqF7g==
|
|
||||||
|
|
||||||
"@material/line-ripple@^0.43.0":
|
|
||||||
version "0.43.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/line-ripple/-/line-ripple-0.43.0.tgz#6cb530bab53f055f3583646a21ad20c1703f3a83"
|
|
||||||
integrity sha512-sXZYW4Em5uLEnAuVsQCO+sVHsTg7J2TOTJ0+akwZFMmd2tmNicjarQdlGIE9iU7Wjm51NOoLAu6Mz+8kLg90bQ==
|
|
||||||
dependencies:
|
|
||||||
"@material/animation" "^0.41.0"
|
|
||||||
"@material/base" "^0.41.0"
|
|
||||||
"@material/theme" "^0.43.0"
|
|
||||||
|
|
||||||
"@material/linear-progress@^0.43.0":
|
|
||||||
version "0.43.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/linear-progress/-/linear-progress-0.43.0.tgz#4821424aa24c78de256e74a91d5be3df55c534d9"
|
|
||||||
integrity sha512-bqkDcob+xp1mFkyBsOkoaLgrtapmz7jznGoI3nmkqyk75EB2XQcn1H8Vr6cnp/jkF4nbKu0GdVJO3VXUFmGmrQ==
|
|
||||||
dependencies:
|
|
||||||
"@material/animation" "^0.41.0"
|
|
||||||
"@material/base" "^0.41.0"
|
|
||||||
"@material/theme" "^0.43.0"
|
|
||||||
|
|
||||||
"@material/list@^0.44.0":
|
|
||||||
version "0.44.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/list/-/list-0.44.0.tgz#cf1910e15b66759334b8618d1110fbcc72c3d326"
|
|
||||||
integrity sha512-35gkN1+XZaau9d9ngyN2x14bzkj/ajZCDm7mbWibDQy272A16j6KuFLQFA8RUQV04OgL4YPVxY87dpCn/p+uTg==
|
|
||||||
dependencies:
|
|
||||||
"@material/base" "^0.41.0"
|
|
||||||
"@material/dom" "^0.41.0"
|
|
||||||
"@material/ripple" "^0.44.0"
|
|
||||||
"@material/rtl" "^0.42.0"
|
|
||||||
"@material/shape" "^0.43.0"
|
|
||||||
"@material/theme" "^0.43.0"
|
|
||||||
"@material/typography" "^0.44.0"
|
|
||||||
|
|
||||||
"@material/menu-surface@^0.44.0":
|
|
||||||
version "0.44.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/menu-surface/-/menu-surface-0.44.0.tgz#902c081df42859b925a5b4502791b3febf48f1ae"
|
|
||||||
integrity sha512-s49kvIlQ4H5wvMD4yeHMMqnamPod06IUagMK6Ry0oTpUANSnyeNXxa3HkScl7DMJiS8IJeV21fSLAzlZYP2PDQ==
|
|
||||||
dependencies:
|
|
||||||
"@material/animation" "^0.41.0"
|
|
||||||
"@material/base" "^0.41.0"
|
|
||||||
"@material/elevation" "^0.44.0"
|
|
||||||
"@material/rtl" "^0.42.0"
|
|
||||||
"@material/shape" "^0.43.0"
|
|
||||||
"@material/theme" "^0.43.0"
|
|
||||||
|
|
||||||
"@material/menu@^0.44.0":
|
|
||||||
version "0.44.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/menu/-/menu-0.44.0.tgz#776ec8a04406266a0a0a13eb140b1fd691e442cb"
|
|
||||||
integrity sha512-92XvAcv9rBW1jQ3UvwJ8zk9hbSRe/FqSuFdZ9fNPE348dCY2pbcdQfnUJTe3ycAN/I1c5frkrhx8F0II+nfbNQ==
|
|
||||||
dependencies:
|
|
||||||
"@material/base" "^0.41.0"
|
|
||||||
"@material/list" "^0.44.0"
|
|
||||||
"@material/menu-surface" "^0.44.0"
|
|
||||||
"@material/ripple" "^0.44.0"
|
|
||||||
"@material/rtl" "^0.42.0"
|
|
||||||
|
|
||||||
"@material/notched-outline@^0.44.0":
|
|
||||||
version "0.44.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/notched-outline/-/notched-outline-0.44.0.tgz#d5a2e1d649921575a7cd2e88ee4581e4a1809573"
|
|
||||||
integrity sha512-c3nqOqUQAmW3h4zBbZVbMRdf4nNTYm0tVwXIAwmcCs5nvAthEHnzHwwFddNP7/9Wju6LZ0uqWn6xlyKly0uipw==
|
|
||||||
dependencies:
|
|
||||||
"@material/animation" "^0.41.0"
|
|
||||||
"@material/base" "^0.41.0"
|
|
||||||
"@material/floating-label" "^0.44.0"
|
|
||||||
"@material/rtl" "^0.42.0"
|
|
||||||
"@material/shape" "^0.43.0"
|
|
||||||
"@material/theme" "^0.43.0"
|
|
||||||
|
|
||||||
"@material/notched-outline@^0.44.1":
|
|
||||||
version "0.44.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/notched-outline/-/notched-outline-0.44.1.tgz#dba4812286ba4c20f0361e6040bf9b9cad307434"
|
|
||||||
integrity sha512-x1ZJtrrqZgXT8gYE7aRF+6hTWpX7XaKZzsuwD+e0HBsogYNNsYmkBdLjl4YwhhFuHhX8vWzgkay41GtbgQx84Q==
|
|
||||||
dependencies:
|
|
||||||
"@material/animation" "^0.41.0"
|
|
||||||
"@material/base" "^0.41.0"
|
|
||||||
"@material/floating-label" "^0.44.1"
|
|
||||||
"@material/rtl" "^0.42.0"
|
|
||||||
"@material/shape" "^0.44.1"
|
|
||||||
"@material/theme" "^0.43.0"
|
|
||||||
|
|
||||||
"@material/radio@^0.44.0":
|
|
||||||
version "0.44.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/radio/-/radio-0.44.0.tgz#f4cacdfabc7d765aa000cb34c5a37966f6d4fd6d"
|
|
||||||
integrity sha512-ar7uhlfHuSwM9JUUjpv7pLDLE0p436cCMxNTpmMjWabfvo3pMWlExvk72Oj81tBgfxY/uASLB3oj4neudXu9JQ==
|
|
||||||
dependencies:
|
|
||||||
"@material/animation" "^0.41.0"
|
|
||||||
"@material/base" "^0.41.0"
|
|
||||||
"@material/ripple" "^0.44.0"
|
|
||||||
"@material/selection-control" "^0.44.0"
|
|
||||||
"@material/theme" "^0.43.0"
|
|
||||||
|
|
||||||
"@material/ripple@^0.44.0":
|
|
||||||
version "0.44.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/ripple/-/ripple-0.44.0.tgz#98920ff8ec4bf5714c97df3d190f02f8a5b476cc"
|
|
||||||
integrity sha512-MlaW4nUDgzS0JOBfsUawXyTOilr0jn+xvTVn6PEaGh2rmhNA54AhixXvdsVUWE9lfmHAsZV0AJHz2z7nunNhbQ==
|
|
||||||
dependencies:
|
|
||||||
"@material/animation" "^0.41.0"
|
|
||||||
"@material/base" "^0.41.0"
|
|
||||||
"@material/feature-targeting" "^0.44.0"
|
|
||||||
"@material/theme" "^0.43.0"
|
|
||||||
|
|
||||||
"@material/ripple@^0.44.1":
|
|
||||||
version "0.44.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/ripple/-/ripple-0.44.1.tgz#79cb2ddf1f998498d877d3e3c46b50fed6f13b01"
|
|
||||||
integrity sha512-prJ1p3bR+GvwAtJgtdeIixsnRVApN3bizGnX7upKoqxsqbBDHj84JxaO8EsG9bjruG/LJu8Fb6WKKdIp2oXHTA==
|
|
||||||
dependencies:
|
|
||||||
"@material/animation" "^0.41.0"
|
|
||||||
"@material/base" "^0.41.0"
|
|
||||||
"@material/feature-targeting" "^0.44.1"
|
|
||||||
"@material/theme" "^0.43.0"
|
|
||||||
|
|
||||||
"@material/rtl@^0.42.0":
|
|
||||||
version "0.42.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/rtl/-/rtl-0.42.0.tgz#1836e78186c2d8b996f6fbf97adab203535335bc"
|
|
||||||
integrity sha512-VrnrKJzhmspsN8WXHuxxBZ69yM5IwhCUqWr1t1eNfw3ZEvEj7i1g3P31HGowKThIN1dc1Wh4LE14rCISWCtv5w==
|
|
||||||
|
|
||||||
"@material/select@^0.44.0":
|
|
||||||
version "0.44.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/select/-/select-0.44.0.tgz#8041b4fe6247d013b0f12685fbdf50aa9ff57b35"
|
|
||||||
integrity sha512-tw3/QIBLuRCT+5IXx4IPiJk7FzeGeR65JEizdRUItH8yzoIiQLs/b2i3KtHM2YBXHgeUcEBF2AOqPX2opdYhug==
|
|
||||||
dependencies:
|
|
||||||
"@material/animation" "^0.41.0"
|
|
||||||
"@material/base" "^0.41.0"
|
|
||||||
"@material/floating-label" "^0.44.0"
|
|
||||||
"@material/line-ripple" "^0.43.0"
|
|
||||||
"@material/menu" "^0.44.0"
|
|
||||||
"@material/menu-surface" "^0.44.0"
|
|
||||||
"@material/notched-outline" "^0.44.0"
|
|
||||||
"@material/ripple" "^0.44.0"
|
|
||||||
"@material/rtl" "^0.42.0"
|
|
||||||
"@material/shape" "^0.43.0"
|
|
||||||
"@material/theme" "^0.43.0"
|
|
||||||
"@material/typography" "^0.44.0"
|
|
||||||
|
|
||||||
"@material/selection-control@^0.44.0":
|
|
||||||
version "0.44.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/selection-control/-/selection-control-0.44.0.tgz#63d5c65a47a9f54f5a0316b5ecdb5e5f35108609"
|
|
||||||
integrity sha512-HgCAPnMVMEj4X4ILkFSifqtZ3Tcc5HkU+Lfk9g0807sCaN/qBKWkYKLH2WJUbW8uk+MXK7DgP1khtS5zzanJWA==
|
|
||||||
dependencies:
|
|
||||||
"@material/ripple" "^0.44.0"
|
|
||||||
|
|
||||||
"@material/selection-control@^0.44.1":
|
|
||||||
version "0.44.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/selection-control/-/selection-control-0.44.1.tgz#77a47354a4c5128fa34e3ba98d9cc26e8a92839a"
|
|
||||||
integrity sha512-Xf1ee2ZV2XJ+rK8OcOD1DZOihfU0uVRdY6iYX/Bqi8k8RXnAbLIBoh6zG3xSwjRNODNvAyHEQaS/ozEfH8eehg==
|
|
||||||
dependencies:
|
|
||||||
"@material/ripple" "^0.44.1"
|
|
||||||
|
|
||||||
"@material/shape@^0.43.0":
|
|
||||||
version "0.43.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/shape/-/shape-0.43.0.tgz#b877acfd8be8abc9ddcf6601eb60dd0588292415"
|
|
||||||
integrity sha512-KGnoQV4G2OQbMe5Lr5Xbk8XNlO93Qi/juxXtd2wrAfiaPmktD8ug0CwdVDOPBOmj9a0gX3Ofi9XWcoU+tLEVjg==
|
|
||||||
|
|
||||||
"@material/shape@^0.44.1":
|
|
||||||
version "0.44.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/shape/-/shape-0.44.1.tgz#ff4d5d42b07c5781306677bffee43234b756ea8e"
|
|
||||||
integrity sha512-8mCDQmyTEhDK+HX8Tap2Lc82QlVySlXU8zDCNkWoIn1ge+UnRezSDjE4y4P1ABegN5PrkJZPartuQ1U0ttIYXw==
|
|
||||||
dependencies:
|
|
||||||
"@material/feature-targeting" "^0.44.1"
|
|
||||||
|
|
||||||
"@material/slider@^0.44.0":
|
|
||||||
version "0.44.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/slider/-/slider-0.44.0.tgz#2055df894eb725e541cde50a544719c07934755b"
|
|
||||||
integrity sha512-Lnn2fdUesXX4O0UpJzveEuOj+og+dXCwhal73u3l3NXEdc/eRgYxwWdF3ww4MmCZ786EwUmjb4vIc9olN4DO3A==
|
|
||||||
dependencies:
|
|
||||||
"@material/animation" "^0.41.0"
|
|
||||||
"@material/base" "^0.41.0"
|
|
||||||
"@material/rtl" "^0.42.0"
|
|
||||||
"@material/theme" "^0.43.0"
|
|
||||||
"@material/typography" "^0.44.0"
|
|
||||||
|
|
||||||
"@material/snackbar@^0.44.0":
|
|
||||||
version "0.44.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/snackbar/-/snackbar-0.44.0.tgz#d98672b849f5f295e4fac2d474a9c80f11945518"
|
|
||||||
integrity sha512-KhCrmJm8Zu/ZZPuRCGfMKsZ0vudINlNgTjlOau0kQ/UgR1xBUvLOE8NjyXZr0RQz5obyW7xpyIWIpscn0IUeyw==
|
|
||||||
dependencies:
|
|
||||||
"@material/animation" "^0.41.0"
|
|
||||||
"@material/base" "^0.41.0"
|
|
||||||
"@material/button" "^0.44.0"
|
|
||||||
"@material/dom" "^0.41.0"
|
|
||||||
"@material/icon-button" "^0.44.0"
|
|
||||||
"@material/ripple" "^0.44.0"
|
|
||||||
"@material/rtl" "^0.42.0"
|
|
||||||
"@material/shape" "^0.43.0"
|
|
||||||
"@material/theme" "^0.43.0"
|
|
||||||
"@material/typography" "^0.44.0"
|
|
||||||
|
|
||||||
"@material/switch@^0.44.0":
|
|
||||||
version "0.44.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/switch/-/switch-0.44.0.tgz#f2cbb447437b12eb3bc7f0ec8318dbd3b4f0afce"
|
|
||||||
integrity sha512-EadCg6lHUF260R2Q/l++vXIITqacvbXlobSoewA5ib6y9BU2g7l13wL1W8xAVJNUMgFa/PyN+EKT3oCql7jZLg==
|
|
||||||
dependencies:
|
|
||||||
"@material/animation" "^0.41.0"
|
|
||||||
"@material/base" "^0.41.0"
|
|
||||||
"@material/elevation" "^0.44.0"
|
|
||||||
"@material/ripple" "^0.44.0"
|
|
||||||
"@material/rtl" "^0.42.0"
|
|
||||||
"@material/selection-control" "^0.44.0"
|
|
||||||
"@material/theme" "^0.43.0"
|
|
||||||
|
|
||||||
"@material/tab-bar@^0.44.0":
|
|
||||||
version "0.44.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/tab-bar/-/tab-bar-0.44.0.tgz#b17d791bd557b1d84892fef1a1d8b8d6fef7c6d6"
|
|
||||||
integrity sha512-kCrt05d61YXyY43SNc0dPGuqysbcLr/KRDBvzpXgE4gv2jCCVhhjAH10KPlx8pthp/UtvrYJHb34acAKEGzdHA==
|
|
||||||
dependencies:
|
|
||||||
"@material/base" "^0.41.0"
|
|
||||||
"@material/elevation" "^0.44.0"
|
|
||||||
"@material/tab" "^0.44.0"
|
|
||||||
"@material/tab-scroller" "^0.44.0"
|
|
||||||
|
|
||||||
"@material/tab-indicator@^0.43.0":
|
|
||||||
version "0.43.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/tab-indicator/-/tab-indicator-0.43.0.tgz#37fd05513ba55ae218d9068c986c2676096fd6eb"
|
|
||||||
integrity sha512-RMNMQpWYghWpM6d0ayfuHEPzTiebKG0bMthViiD6tly8PubmOT8mShNhPm8ihybhDPUOLSz+7V4QNE5wikLEYg==
|
|
||||||
dependencies:
|
|
||||||
"@material/animation" "^0.41.0"
|
|
||||||
"@material/base" "^0.41.0"
|
|
||||||
"@material/theme" "^0.43.0"
|
|
||||||
|
|
||||||
"@material/tab-scroller@^0.44.0":
|
|
||||||
version "0.44.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/tab-scroller/-/tab-scroller-0.44.0.tgz#82d092ed45d2ee9d82038bed318e6ff6bdc36dad"
|
|
||||||
integrity sha512-Ufd3NWBN11kY2oA7bGmTYWGP1uz2mq0tfDM0JOiqoLMgD7y3Z18kmxnpq2qkg1vi4kvix28hBYGGMfLlq9rGDA==
|
|
||||||
dependencies:
|
|
||||||
"@material/animation" "^0.41.0"
|
|
||||||
"@material/base" "^0.41.0"
|
|
||||||
"@material/tab" "^0.44.0"
|
|
||||||
|
|
||||||
"@material/tab@^0.44.0":
|
|
||||||
version "0.44.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/tab/-/tab-0.44.0.tgz#254b92cff99015f0bd59a86d08d3f1c4744d0742"
|
|
||||||
integrity sha512-czrbGjtKkmUS3iYBX523xT5GOkjP0h+0x9fTnw+heFNpw5dCn6cZvlj3D9ayZU+ZH93x68TFhFVBuLU5f0EBXw==
|
|
||||||
dependencies:
|
|
||||||
"@material/base" "^0.41.0"
|
|
||||||
"@material/ripple" "^0.44.0"
|
|
||||||
"@material/rtl" "^0.42.0"
|
|
||||||
"@material/tab-indicator" "^0.43.0"
|
|
||||||
"@material/theme" "^0.43.0"
|
|
||||||
"@material/typography" "^0.44.0"
|
|
||||||
|
|
||||||
"@material/textfield@^0.44.0":
|
|
||||||
version "0.44.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/textfield/-/textfield-0.44.0.tgz#277b33948ddff33f7f643323895e5a683f013601"
|
|
||||||
integrity sha512-IMBwMcE82eVU+Wifpu0t84tozvBPLCeqQELDtZNYujKg3RxaultzJLwIyGKPMZ9R4yPEpV2vgXPGKE+2/AWt0g==
|
|
||||||
dependencies:
|
|
||||||
"@material/animation" "^0.41.0"
|
|
||||||
"@material/base" "^0.41.0"
|
|
||||||
"@material/floating-label" "^0.44.0"
|
|
||||||
"@material/line-ripple" "^0.43.0"
|
|
||||||
"@material/notched-outline" "^0.44.0"
|
|
||||||
"@material/ripple" "^0.44.0"
|
|
||||||
"@material/rtl" "^0.42.0"
|
|
||||||
"@material/shape" "^0.43.0"
|
|
||||||
"@material/theme" "^0.43.0"
|
|
||||||
"@material/typography" "^0.44.0"
|
|
||||||
|
|
||||||
"@material/textfield@^0.44.1":
|
|
||||||
version "0.44.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/textfield/-/textfield-0.44.1.tgz#2bba41cc94e68e328683997a1acf222b643dea9c"
|
|
||||||
integrity sha512-zy+56+uqr+L9DGrdOfQjOIMdKlai/7ruyqVfqIY6ieABM7LEGsOsxHhyExQmXo9IiuFhrOceWKFa4yIb8jBsmQ==
|
|
||||||
dependencies:
|
|
||||||
"@material/animation" "^0.41.0"
|
|
||||||
"@material/base" "^0.41.0"
|
|
||||||
"@material/floating-label" "^0.44.1"
|
|
||||||
"@material/line-ripple" "^0.43.0"
|
|
||||||
"@material/notched-outline" "^0.44.1"
|
|
||||||
"@material/ripple" "^0.44.1"
|
|
||||||
"@material/rtl" "^0.42.0"
|
|
||||||
"@material/shape" "^0.44.1"
|
|
||||||
"@material/theme" "^0.43.0"
|
|
||||||
"@material/typography" "^0.44.1"
|
|
||||||
|
|
||||||
"@material/theme@^0.43.0":
|
|
||||||
version "0.43.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/theme/-/theme-0.43.0.tgz#6d9fa113c82e841817882172c152d60d2d203ca6"
|
|
||||||
integrity sha512-/zndZL6EihI18v2mYd4O8xvOBAAXmLeHyHVK28LozSAaJ9okQgD25wq5Ktk95oMTmPIC+rH66KcK6371ivNk8g==
|
|
||||||
|
|
||||||
"@material/toolbar@^0.44.0":
|
|
||||||
version "0.44.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/toolbar/-/toolbar-0.44.0.tgz#6689aecdeccc78b7a890a3abbe8b68a2c6339307"
|
|
||||||
integrity sha512-YgLlOFQ5VzFLQBpXYSMviEbYox0fia+sasHuYPUhTAtas1ExVt9EEiIolDSVvhv2PruTReKKefxSbXAqGlOHog==
|
|
||||||
dependencies:
|
|
||||||
"@material/base" "^0.41.0"
|
|
||||||
"@material/elevation" "^0.44.0"
|
|
||||||
"@material/ripple" "^0.44.0"
|
|
||||||
"@material/rtl" "^0.42.0"
|
|
||||||
"@material/theme" "^0.43.0"
|
|
||||||
"@material/typography" "^0.44.0"
|
|
||||||
|
|
||||||
"@material/top-app-bar@^0.44.0":
|
|
||||||
version "0.44.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/top-app-bar/-/top-app-bar-0.44.0.tgz#2495c7f9567568fb961ccced24f479c4806a72af"
|
|
||||||
integrity sha512-tf0yXQJARYs8UPaH8oo3LnsSHEiur7Zm8Fc3hv3F0gNRRaZYBjwsMQMVbZZaWoQCWskMALyntBg+Fo18zdgDxw==
|
|
||||||
dependencies:
|
|
||||||
"@material/animation" "^0.41.0"
|
|
||||||
"@material/base" "^0.41.0"
|
|
||||||
"@material/elevation" "^0.44.0"
|
|
||||||
"@material/ripple" "^0.44.0"
|
|
||||||
"@material/rtl" "^0.42.0"
|
|
||||||
"@material/shape" "^0.43.0"
|
|
||||||
"@material/theme" "^0.43.0"
|
|
||||||
"@material/typography" "^0.44.0"
|
|
||||||
|
|
||||||
"@material/typography@^0.44.0":
|
|
||||||
version "0.44.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/typography/-/typography-0.44.0.tgz#cf61dce2ee89bfa084d86e1b0f270a585bf9dfaf"
|
|
||||||
integrity sha512-m4SjA9OjZRDKowN3cPzEa8e2GlTlEn3ZmW/Fy9eRNSp83iY+8a0xl6kCaF80v5qAVwVcpfEFyEHWxMJtkBw2uA==
|
|
||||||
|
|
||||||
"@material/typography@^0.44.1":
|
|
||||||
version "0.44.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/typography/-/typography-0.44.1.tgz#a94f01172f9122180bc2ce0aa55658183a35590d"
|
|
||||||
integrity sha512-wMXHusg+Lp5Fdgoj3m0c+Lt6GCeGSh3EPRtQ1TQ2bwdBa0et2FqBaQRgXoq3tVmr0O/7unTfa0DoXlh4nVp1wA==
|
|
||||||
dependencies:
|
|
||||||
"@material/feature-targeting" "^0.44.1"
|
|
||||||
|
|
||||||
focus-trap@^4.0.2:
|
|
||||||
version "4.0.2"
|
|
||||||
resolved "https://registry.yarnpkg.com/focus-trap/-/focus-trap-4.0.2.tgz#4ee2b96547c9ea0e4252a2d4b2cca68944194663"
|
|
||||||
integrity sha512-HtLjfAK7Hp2qbBtLS6wEznID1mPT+48ZnP2nkHzgjpL4kroYHg0CdqJ5cTXk+UO5znAxF5fRUkhdyfgrhh8Lzw==
|
|
||||||
dependencies:
|
|
||||||
tabbable "^3.1.2"
|
|
||||||
xtend "^4.0.1"
|
|
||||||
|
|
||||||
material-components-web@^0.44.0:
|
|
||||||
version "0.44.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/material-components-web/-/material-components-web-0.44.0.tgz#ff782e8d7bdd8212d3c6022a731258d0d42da531"
|
|
||||||
integrity sha512-BSRLf58SMVhAvlDhJDlcgYuvzeMwbMHKTJ7oIB8LaM24ZpXBxP9XCYJpKheMtiVLrgllCGDlJ/47OIDReHQXdQ==
|
|
||||||
dependencies:
|
|
||||||
"@material/animation" "^0.41.0"
|
|
||||||
"@material/auto-init" "^0.41.0"
|
|
||||||
"@material/base" "^0.41.0"
|
|
||||||
"@material/button" "^0.44.0"
|
|
||||||
"@material/card" "^0.44.0"
|
|
||||||
"@material/checkbox" "^0.44.0"
|
|
||||||
"@material/chips" "^0.44.0"
|
|
||||||
"@material/dialog" "^0.44.0"
|
|
||||||
"@material/dom" "^0.41.0"
|
|
||||||
"@material/drawer" "^0.44.0"
|
|
||||||
"@material/elevation" "^0.44.0"
|
|
||||||
"@material/fab" "^0.44.0"
|
|
||||||
"@material/feature-targeting" "^0.44.0"
|
|
||||||
"@material/floating-label" "^0.44.0"
|
|
||||||
"@material/form-field" "^0.44.0"
|
|
||||||
"@material/grid-list" "^0.44.0"
|
|
||||||
"@material/icon-button" "^0.44.0"
|
|
||||||
"@material/icon-toggle" "^0.44.0"
|
|
||||||
"@material/image-list" "^0.44.0"
|
|
||||||
"@material/layout-grid" "^0.41.0"
|
|
||||||
"@material/line-ripple" "^0.43.0"
|
|
||||||
"@material/linear-progress" "^0.43.0"
|
|
||||||
"@material/list" "^0.44.0"
|
|
||||||
"@material/menu" "^0.44.0"
|
|
||||||
"@material/menu-surface" "^0.44.0"
|
|
||||||
"@material/notched-outline" "^0.44.0"
|
|
||||||
"@material/radio" "^0.44.0"
|
|
||||||
"@material/ripple" "^0.44.0"
|
|
||||||
"@material/rtl" "^0.42.0"
|
|
||||||
"@material/select" "^0.44.0"
|
|
||||||
"@material/selection-control" "^0.44.0"
|
|
||||||
"@material/shape" "^0.43.0"
|
|
||||||
"@material/slider" "^0.44.0"
|
|
||||||
"@material/snackbar" "^0.44.0"
|
|
||||||
"@material/switch" "^0.44.0"
|
|
||||||
"@material/tab" "^0.44.0"
|
|
||||||
"@material/tab-bar" "^0.44.0"
|
|
||||||
"@material/tab-indicator" "^0.43.0"
|
|
||||||
"@material/tab-scroller" "^0.44.0"
|
|
||||||
"@material/textfield" "^0.44.0"
|
|
||||||
"@material/theme" "^0.43.0"
|
|
||||||
"@material/toolbar" "^0.44.0"
|
|
||||||
"@material/top-app-bar" "^0.44.0"
|
|
||||||
"@material/typography" "^0.44.0"
|
|
||||||
|
|
||||||
tabbable@^3.1.2:
|
|
||||||
version "3.1.2"
|
|
||||||
resolved "https://registry.yarnpkg.com/tabbable/-/tabbable-3.1.2.tgz#f2d16cccd01f400e38635c7181adfe0ad965a4a2"
|
|
||||||
integrity sha512-wjB6puVXTYO0BSFtCmWQubA/KIn7Xvajw0x0l6eJUudMG/EAiJvIUnyNX6xO4NpGrJ16lbD0eUseB9WxW0vlpQ==
|
|
||||||
|
|
||||||
xtend@^4.0.1:
|
|
||||||
version "4.0.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af"
|
|
||||||
integrity sha1-pcbVMr5lbiPbgg77lDofBJmNY68=
|
|
Before Width: | Height: | Size: 537 B |
|
@ -1,42 +0,0 @@
|
||||||
{
|
|
||||||
"manifest_version": 2,
|
|
||||||
"name": "Coder",
|
|
||||||
"version": "1",
|
|
||||||
"icons": {
|
|
||||||
"128": "icon_128.png"
|
|
||||||
},
|
|
||||||
"permissions": [
|
|
||||||
"storage",
|
|
||||||
"webview",
|
|
||||||
"http://*/*",
|
|
||||||
"https://*/*"
|
|
||||||
],
|
|
||||||
"app": {
|
|
||||||
"background": {
|
|
||||||
"scripts": [
|
|
||||||
"out/background.js"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"content": {
|
|
||||||
"scripts": [
|
|
||||||
"out/content.js"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"commands": {
|
|
||||||
"toggle-feature-foo": {
|
|
||||||
"suggested_key": {
|
|
||||||
"default": "Ctrl+W"
|
|
||||||
},
|
|
||||||
"description": "Toggle feature foo",
|
|
||||||
"global": true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"sockets": {
|
|
||||||
"tcpServer": {
|
|
||||||
"listen": [
|
|
||||||
""
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,9 +0,0 @@
|
||||||
{
|
|
||||||
"name": "@coder/chrome-app",
|
|
||||||
"dependencies": {
|
|
||||||
"@types/chrome": "^0.0.79"
|
|
||||||
},
|
|
||||||
"scripts": {
|
|
||||||
"build": "../../../node_modules/.bin/webpack --config ./webpack.config.js"
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,13 +0,0 @@
|
||||||
/// <reference path="../node_modules/@types/chrome/index.d.ts" />
|
|
||||||
|
|
||||||
// tslint:disable-next-line:no-any
|
|
||||||
const chromeApp = (<any>chrome).app;
|
|
||||||
|
|
||||||
chromeApp.runtime.onLaunched.addListener(() => {
|
|
||||||
chromeApp.window.create("src/index.html", {
|
|
||||||
outerBounds: {
|
|
||||||
width: 400,
|
|
||||||
height: 500,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,92 +0,0 @@
|
||||||
//@ts-ignore
|
|
||||||
import { TcpHost, TcpServer, TcpConnection } from "@coder/app/common/src/app";
|
|
||||||
import { Event, Emitter } from "@coder/events/src";
|
|
||||||
|
|
||||||
export const tcpHost: TcpHost = {
|
|
||||||
listen(host: string, port: number): Promise<TcpServer> {
|
|
||||||
const socketApi: {
|
|
||||||
readonly tcpServer: {
|
|
||||||
create(props: {}, cb: (createInfo: { readonly socketId: number }) => void): void;
|
|
||||||
listen(socketId: number, address: string, port: number, callback: (result: number) => void): void;
|
|
||||||
disconnect(socketId: number, callback: () => void): void;
|
|
||||||
|
|
||||||
readonly onAccept: {
|
|
||||||
addListener(callback: (info: { readonly socketId: number; readonly clientSocketId: number }) => void): void;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
readonly tcp: {
|
|
||||||
readonly onReceive: {
|
|
||||||
addListener(callback: (info: { readonly socketId: number; readonly data: ArrayBuffer; }) => void): void;
|
|
||||||
};
|
|
||||||
close(socketId: number, callback?: () => void): void;
|
|
||||||
send(socketId: number, data: ArrayBuffer, callback?: () => void): void;
|
|
||||||
setPaused(socketId: number, value: boolean): void;
|
|
||||||
};
|
|
||||||
// tslint:disable-next-line:no-any
|
|
||||||
} = (<any>chrome).sockets;
|
|
||||||
|
|
||||||
return new Promise((resolve, reject): void => {
|
|
||||||
socketApi.tcpServer.create({}, (createInfo) => {
|
|
||||||
const serverSocketId = createInfo.socketId;
|
|
||||||
socketApi.tcpServer.listen(serverSocketId, host, port, (result) => {
|
|
||||||
if (result < 0) {
|
|
||||||
return reject("Failed to listen: " + chrome.runtime.lastError);
|
|
||||||
}
|
|
||||||
|
|
||||||
const connectionEmitter = new Emitter<TcpConnection>();
|
|
||||||
|
|
||||||
socketApi.tcpServer.onAccept.addListener((info) => {
|
|
||||||
if (info.socketId !== serverSocketId) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const dataEmitter = new Emitter<ArrayBuffer>();
|
|
||||||
|
|
||||||
socketApi.tcp.onReceive.addListener((recvInfo) => {
|
|
||||||
if (recvInfo.socketId !== info.clientSocketId) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
dataEmitter.emit(recvInfo.data);
|
|
||||||
});
|
|
||||||
|
|
||||||
socketApi.tcp.setPaused(info.clientSocketId, false);
|
|
||||||
|
|
||||||
connectionEmitter.emit({
|
|
||||||
send: (data): Promise<void> => {
|
|
||||||
return new Promise<void>((res): void => {
|
|
||||||
socketApi.tcp.send(info.clientSocketId, data, () => {
|
|
||||||
res();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
},
|
|
||||||
close: (): Promise<void> => {
|
|
||||||
return new Promise((res): void => {
|
|
||||||
socketApi.tcp.close(info.clientSocketId, () => {
|
|
||||||
res();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
},
|
|
||||||
get onData(): Event<ArrayBuffer> {
|
|
||||||
return dataEmitter.event;
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
resolve({
|
|
||||||
get onConnection(): Event<TcpConnection> {
|
|
||||||
return connectionEmitter.event;
|
|
||||||
},
|
|
||||||
close: (): Promise<void> => {
|
|
||||||
return new Promise((res): void => {
|
|
||||||
socketApi.tcpServer.disconnect(serverSocketId, () => {
|
|
||||||
res();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
},
|
|
||||||
};
|
|
|
@ -1,33 +0,0 @@
|
||||||
import { create } from "@coder/app/common/src/app";
|
|
||||||
import { tcpHost } from "./chome";
|
|
||||||
|
|
||||||
create({
|
|
||||||
storage: {
|
|
||||||
get: <T>(key: string): Promise<T | undefined> => {
|
|
||||||
return new Promise<T | undefined>((resolve, reject): void => {
|
|
||||||
try {
|
|
||||||
chrome.storage.sync.get(key, (items) => {
|
|
||||||
resolve(items[key]);
|
|
||||||
});
|
|
||||||
} catch (ex) {
|
|
||||||
reject(ex);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
set: <T>(key: string, value: T): Promise<void> => {
|
|
||||||
return new Promise<void>((resolve, reject): void => {
|
|
||||||
try {
|
|
||||||
chrome.storage.sync.set({
|
|
||||||
[key]: value,
|
|
||||||
}, () => {
|
|
||||||
resolve();
|
|
||||||
});
|
|
||||||
} catch (ex) {
|
|
||||||
reject(ex);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
},
|
|
||||||
tcp: tcpHost,
|
|
||||||
node: document.getElementById("main") as HTMLDivElement,
|
|
||||||
});
|
|
|
@ -1,15 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<meta http-equiv="Content-Security-Policy" content="style-src 'self' https://use.typekit.net; font-src 'self' https://use.typekit.net;">
|
|
||||||
<link rel="stylesheet" type="text/css" href="/out/main.css">
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<div id="main"></div>
|
|
||||||
<script src="/out/content.js"></script>
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
|
@ -1,37 +0,0 @@
|
||||||
const path = require("path");
|
|
||||||
const webpack = require("webpack");
|
|
||||||
const merge = require("webpack-merge");
|
|
||||||
const BundleAnalyzerPlugin = require("webpack-bundle-analyzer").BundleAnalyzerPlugin;
|
|
||||||
const HtmlWebpackPlugin = require("html-webpack-plugin");
|
|
||||||
const prod = process.env.NODE_ENV === "production";
|
|
||||||
|
|
||||||
module.exports = [
|
|
||||||
merge(require(path.join(__dirname, "../../../scripts", "webpack.general.config.js"))(), {
|
|
||||||
devtool: "none",
|
|
||||||
mode: "development",
|
|
||||||
target: "web",
|
|
||||||
output: {
|
|
||||||
path: path.join(__dirname, "out"),
|
|
||||||
filename: "background.js",
|
|
||||||
},
|
|
||||||
entry: [
|
|
||||||
"./packages/app/chrome/src/background.ts"
|
|
||||||
],
|
|
||||||
plugins: [
|
|
||||||
]
|
|
||||||
}),
|
|
||||||
merge(require(path.join(__dirname, "../../../scripts", "webpack.general.config.js"))(), {
|
|
||||||
devtool: "none",
|
|
||||||
mode: "development",
|
|
||||||
target: "web",
|
|
||||||
output: {
|
|
||||||
path: path.join(__dirname, "out"),
|
|
||||||
filename: "content.js",
|
|
||||||
},
|
|
||||||
entry: [
|
|
||||||
"./packages/app/chrome/src/content.ts"
|
|
||||||
],
|
|
||||||
plugins: [
|
|
||||||
]
|
|
||||||
}),
|
|
||||||
];
|
|
|
@ -1,22 +0,0 @@
|
||||||
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
|
|
||||||
# yarn lockfile v1
|
|
||||||
|
|
||||||
|
|
||||||
"@types/chrome@^0.0.79":
|
|
||||||
version "0.0.79"
|
|
||||||
resolved "https://registry.yarnpkg.com/@types/chrome/-/chrome-0.0.79.tgz#1c83b35bd9b21b6204fb56e4816a1ea65dc013e5"
|
|
||||||
integrity sha512-4+Xducpig6lpwVX65Hk8KSZwRoURHXMDbd38SDNcV8TBaw4xyJki39fjB1io2h7ip+BsyFvgTm9OxR5qneLPiA==
|
|
||||||
dependencies:
|
|
||||||
"@types/filesystem" "*"
|
|
||||||
|
|
||||||
"@types/filesystem@*":
|
|
||||||
version "0.0.29"
|
|
||||||
resolved "https://registry.yarnpkg.com/@types/filesystem/-/filesystem-0.0.29.tgz#ee3748eb5be140dcf980c3bd35f11aec5f7a3748"
|
|
||||||
integrity sha512-85/1KfRedmfPGsbK8YzeaQUyV1FQAvMPMTuWFQ5EkLd2w7szhNO96bk3Rh/SKmOfd9co2rCLf0Voy4o7ECBOvw==
|
|
||||||
dependencies:
|
|
||||||
"@types/filewriter" "*"
|
|
||||||
|
|
||||||
"@types/filewriter@*":
|
|
||||||
version "0.0.28"
|
|
||||||
resolved "https://registry.yarnpkg.com/@types/filewriter/-/filewriter-0.0.28.tgz#c054e8af4d9dd75db4e63abc76f885168714d4b3"
|
|
||||||
integrity sha1-wFTor02d11205jq8dviFFocU1LM=
|
|
|
@ -1,13 +0,0 @@
|
||||||
{
|
|
||||||
"name": "@coder/app-common",
|
|
||||||
"main": "src/app.ts",
|
|
||||||
"dependencies": {
|
|
||||||
"material-components-web": "^0.44.0",
|
|
||||||
"react": "^16.8.1",
|
|
||||||
"react-dom": "^16.8.1"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@types/react": "^16.8.2",
|
|
||||||
"@types/react-dom": "^16.8.0"
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,279 +0,0 @@
|
||||||
@font-face {
|
|
||||||
font-family: 'aktiv-grotesk';
|
|
||||||
font-weight: 400;
|
|
||||||
// src: url("fonts/AktivGroteskRegular.ttf"); /* IE9 Compat Modes */
|
|
||||||
src: url("fonts/AktivGroteskRegular.woff2") format("woff2"), url("fonts/AktivGroteskRegular.woff") format("woff"); /* Pretty Modern Browsers */
|
|
||||||
}
|
|
||||||
|
|
||||||
@font-face {
|
|
||||||
font-family: 'aktiv-grotesk';
|
|
||||||
font-weight: 500;
|
|
||||||
src: url("fonts/AktivGroteskMedium.woff2") format("woff2"), url("fonts/AktivGroteskMedium.woff") format("woff"); /* Pretty Modern Browsers */
|
|
||||||
// src: url("fonts/AktivGroteskMedium.ttf");
|
|
||||||
}
|
|
||||||
|
|
||||||
@font-face {
|
|
||||||
font-family: 'aktiv-grotesk';
|
|
||||||
font-weight: 700;
|
|
||||||
src: url("fonts/AktivGroteskBold.woff2") format("woff2"), url("fonts/AktivGroteskBold.woff") format("woff"); /* Pretty Modern Browsers */
|
|
||||||
// src: url("fonts/AktivGroteskBold.ttf") format("ttf"); /* IE9 Compat Modes */
|
|
||||||
}
|
|
||||||
|
|
||||||
body, button, input {
|
|
||||||
font-family: 'aktiv-grotesk',sans-serif !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
|
||||||
margin: 0;
|
|
||||||
background-color: #F6F8FB;
|
|
||||||
--mdc-theme-primary: #2A2E37;
|
|
||||||
}
|
|
||||||
|
|
||||||
webview {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
bottom: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
opacity: 0;
|
|
||||||
pointer-events: none;
|
|
||||||
transition: 150ms opacity ease;
|
|
||||||
|
|
||||||
&.active {
|
|
||||||
opacity: 1;
|
|
||||||
pointer-events: all;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.logo-fill {
|
|
||||||
fill: #2A2E37;
|
|
||||||
}
|
|
||||||
|
|
||||||
.main {
|
|
||||||
& > .header {
|
|
||||||
width: 100%;
|
|
||||||
height: 71px;
|
|
||||||
border-bottom: 1px solid rgba(117, 122, 131, 0.1);
|
|
||||||
display: flex;
|
|
||||||
margin-bottom: 60px;
|
|
||||||
|
|
||||||
.logo {
|
|
||||||
max-height: fit-content;
|
|
||||||
width: 145px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.shrinker {
|
|
||||||
max-width: 1145px;
|
|
||||||
width: 100%;
|
|
||||||
margin: 0 auto;
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.content {
|
|
||||||
max-width: 960px;
|
|
||||||
width: 100%;
|
|
||||||
padding-bottom: 100px;
|
|
||||||
margin: 0 auto;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.servers {
|
|
||||||
color: #2B343B;
|
|
||||||
|
|
||||||
& > .header {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
align-items: center;
|
|
||||||
padding-bottom: 21px;
|
|
||||||
|
|
||||||
h3 {
|
|
||||||
font-size: 24px;
|
|
||||||
font-weight: 500;
|
|
||||||
letter-spacing: 0.35px;
|
|
||||||
line-height: 33px;
|
|
||||||
margin: 0;
|
|
||||||
margin-left: 30px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.add-server {
|
|
||||||
margin-left: auto;
|
|
||||||
border-radius: 24px;
|
|
||||||
font-weight: bold;
|
|
||||||
font-size: 14px;
|
|
||||||
letter-spacing: 1.25px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.refresh {
|
|
||||||
margin-left: 16px;
|
|
||||||
margin-right: 15px;
|
|
||||||
cursor: pointer;
|
|
||||||
|
|
||||||
svg {
|
|
||||||
@keyframes rotate {
|
|
||||||
100% { transform: rotate(360deg); }
|
|
||||||
}
|
|
||||||
|
|
||||||
&.refreshing {
|
|
||||||
animation: rotate 1s linear infinite;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
& > .grid {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: 1fr 1.6fr 1.3fr 1.1fr 0.6fr 0.4fr;
|
|
||||||
box-shadow: 0 18px 80px 10px rgba(69, 65, 78, 0.08);
|
|
||||||
border-radius: 0 0 5px 5px;
|
|
||||||
|
|
||||||
.mdc-linear-progress {
|
|
||||||
grid-column-start: 1;
|
|
||||||
grid-column-end: 7;
|
|
||||||
// height: 0;
|
|
||||||
position: relative;
|
|
||||||
--mdc-theme-primary: rgb(107, 109, 102);
|
|
||||||
height: 5px;
|
|
||||||
|
|
||||||
&:after {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
bottom: 0;
|
|
||||||
right: 0;
|
|
||||||
background-color: #2A2E37;
|
|
||||||
transition: 500ms opacity ease;
|
|
||||||
content: " ";
|
|
||||||
}
|
|
||||||
|
|
||||||
&.loading {
|
|
||||||
&:after {
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.title, .value {
|
|
||||||
padding-top: 14px;
|
|
||||||
padding-bottom: 14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.title {
|
|
||||||
background-color: var(--mdc-theme-primary);
|
|
||||||
font-size: 10px;
|
|
||||||
color: #9D9FA4;
|
|
||||||
font-weight: bold;
|
|
||||||
letter-spacing: 2px;
|
|
||||||
line-height: 12px;
|
|
||||||
text-transform: uppercase;
|
|
||||||
// padding-top: 15px;
|
|
||||||
// padding-bottom: 10px;
|
|
||||||
|
|
||||||
&:first-child {
|
|
||||||
padding-left: 30px;
|
|
||||||
border-radius: 10px 0 0 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:nth-child(6) {
|
|
||||||
padding-right: 30px;
|
|
||||||
border-radius: 0 10px 0 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.servername {
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.value {
|
|
||||||
border-top: 1px solid #EBEBF2;
|
|
||||||
font-size: 14px;
|
|
||||||
letter-spacing: 0.2px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
color: #717680;
|
|
||||||
background-color: white;
|
|
||||||
|
|
||||||
&.dark {
|
|
||||||
background-color: #F6F8FB;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.servername {
|
|
||||||
.logo {
|
|
||||||
height: 25px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.strong {
|
|
||||||
font-weight: 600;
|
|
||||||
color: #2B343B;
|
|
||||||
font-size: 14px;
|
|
||||||
letter-spacing: 0.6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.status {
|
|
||||||
padding-left: 36px;
|
|
||||||
|
|
||||||
span {
|
|
||||||
margin-left: 7px;
|
|
||||||
line-height: 0px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.buttons {
|
|
||||||
button {
|
|
||||||
margin-left: auto;
|
|
||||||
border-radius: 24px;
|
|
||||||
border: 1px solid #CFD1D7;
|
|
||||||
font-size: 14px;
|
|
||||||
font-weight: bold;
|
|
||||||
letter-spacing: 1.25px;
|
|
||||||
line-height: 16px;
|
|
||||||
padding-left: 18px;
|
|
||||||
padding-right: 18px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.icons {
|
|
||||||
padding-left: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:last-child {
|
|
||||||
border-bottom-right-radius: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:nth-last-child(6) {
|
|
||||||
border-bottom-left-radius: 5px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.flex-row {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
}
|
|
||||||
|
|
||||||
.floater {
|
|
||||||
box-shadow: 0 8px 80px 10px rgba(69, 65, 78, 0.08);
|
|
||||||
border-radius: 10px;
|
|
||||||
padding: 3em;
|
|
||||||
min-width: 300px;
|
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
& > h1 {
|
|
||||||
font-size: 3.5em;
|
|
||||||
margin-top: 0px;
|
|
||||||
|
|
||||||
// margin-bottom: 0px;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.mdc-ripple-upgraded--unbounded {
|
|
||||||
padding: 2px;
|
|
||||||
padding-top: 5px;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
|
@ -1,33 +0,0 @@
|
||||||
//@ts-ignore
|
|
||||||
import { MDCTextField } from "@material/textfield";
|
|
||||||
import { TcpHost } from "./connection";
|
|
||||||
import { StorageProvider } from "./storage";
|
|
||||||
import "material-components-web/dist/material-components-web.css";
|
|
||||||
import "./app.scss";
|
|
||||||
import "./tooltip.scss";
|
|
||||||
|
|
||||||
import * as React from "react";
|
|
||||||
import { render } from "react-dom";
|
|
||||||
import { Main } from "./containers";
|
|
||||||
|
|
||||||
export * from "./connection";
|
|
||||||
export interface App {
|
|
||||||
readonly tcp: TcpHost;
|
|
||||||
readonly storage: StorageProvider;
|
|
||||||
readonly node: HTMLElement;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface RegisteredServer {
|
|
||||||
readonly host: "coder" | "self";
|
|
||||||
readonly hostname: string;
|
|
||||||
readonly name: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const create = async (app: App): Promise<void> => {
|
|
||||||
let servers = await app.storage.get<RegisteredServer[]>("servers");
|
|
||||||
if (!servers) {
|
|
||||||
servers = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
render(<Main />, app.node);
|
|
||||||
};
|
|
|
@ -1,17 +0,0 @@
|
||||||
import { Event } from "@coder/events";
|
|
||||||
import { TunnelCloseEvent } from "@coder/tunnel/src/client";
|
|
||||||
|
|
||||||
export interface TcpHost {
|
|
||||||
listen(host: string, port: number): Promise<TcpServer>;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface TcpServer {
|
|
||||||
readonly onConnection: Event<TcpConnection>;
|
|
||||||
close(): Promise<void>;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface TcpConnection {
|
|
||||||
readonly onData: Event<ArrayBuffer>;
|
|
||||||
send(data: ArrayBuffer): Promise<void>;
|
|
||||||
close(): Promise<void>;
|
|
||||||
}
|
|
|
@ -1,573 +0,0 @@
|
||||||
//@ts-ignore
|
|
||||||
import { MDCRipple } from "@material/ripple";
|
|
||||||
//@ts-ignore
|
|
||||||
import { MDCTextField } from "@material/textfield";
|
|
||||||
//@ts-ignore
|
|
||||||
import { MDCLinearProgress } from "@material/linear-progress";
|
|
||||||
import * as React from "react";
|
|
||||||
import * as ReactDOM from "react-dom";
|
|
||||||
import { RegisteredServer } from "./app";
|
|
||||||
|
|
||||||
// tslint:disable-next-line:no-any
|
|
||||||
declare var WebSettings: any;
|
|
||||||
|
|
||||||
interface AuthedUser {
|
|
||||||
readonly username: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class Main extends React.Component<void, {
|
|
||||||
readonly view: "servers" | "add-server";
|
|
||||||
readonly loading: boolean;
|
|
||||||
}> {
|
|
||||||
private webview: HTMLWebViewElement | undefined;
|
|
||||||
|
|
||||||
public constructor(props: void) {
|
|
||||||
super(props);
|
|
||||||
this.state = {
|
|
||||||
view: "servers",
|
|
||||||
loading: false,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public componentDidMount(): void {
|
|
||||||
window.addEventListener("message", (event) => {
|
|
||||||
if (event.data === "back") {
|
|
||||||
if (this.webview) {
|
|
||||||
this.webview.classList.remove("active");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (event.data === "loaded") {
|
|
||||||
if (this.webview) {
|
|
||||||
// this.setState({ loading: false });
|
|
||||||
// this.webview.classList.add("active");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (this.webview) {
|
|
||||||
this.webview.addEventListener("error", (event) => {
|
|
||||||
console.error(event);
|
|
||||||
});
|
|
||||||
this.webview.addEventListener("loadstart", (event) => {
|
|
||||||
this.setState({ loading: true });
|
|
||||||
});
|
|
||||||
this.webview.addEventListener("loadstop", (event) => {
|
|
||||||
this.setState({ loading: false });
|
|
||||||
this.webview!.classList.add("active");
|
|
||||||
// tslint:disable-next-line:no-any
|
|
||||||
const cw = (this.webview as any).contentWindow as Window;
|
|
||||||
cw.postMessage("app", "*");
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public render(): JSX.Element {
|
|
||||||
return (
|
|
||||||
<div className="main">
|
|
||||||
<div className="header">
|
|
||||||
<div className="shrinker">
|
|
||||||
<Logo />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="content">
|
|
||||||
{((): JSX.Element => {
|
|
||||||
switch (this.state.view) {
|
|
||||||
case "servers":
|
|
||||||
return (
|
|
||||||
<Servers servers={[
|
|
||||||
{
|
|
||||||
host: "coder",
|
|
||||||
hostname: "--",
|
|
||||||
name: "Coder",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
host: "self",
|
|
||||||
hostname: "http://localhost:8080",
|
|
||||||
name: "Dev Server",
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
user={{
|
|
||||||
username: "Kyle",
|
|
||||||
}}
|
|
||||||
onSelect={(server): void => {
|
|
||||||
if (this.webview) {
|
|
||||||
this.webview.setAttribute("src", server.hostname);
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
onAddServer={() => this.setState({ view: "add-server" })}
|
|
||||||
loading={this.state.loading}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
case "add-server":
|
|
||||||
return (
|
|
||||||
<div>Add server</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
})()}
|
|
||||||
</div>
|
|
||||||
<webview ref={(wv: HTMLWebViewElement): HTMLWebViewElement => this.webview = wv}></webview>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class AddServer extends React.Component {
|
|
||||||
public render(): JSX.Element {
|
|
||||||
return (
|
|
||||||
<div className="add-server">
|
|
||||||
<h3>Add Server</h3>
|
|
||||||
<p>Something about what you can do once you add your own server. A link to setup guides for this would be great as well.</p>
|
|
||||||
<Input label="Address" id="address" />
|
|
||||||
<br></br>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class Servers extends React.Component<{
|
|
||||||
readonly user?: AuthedUser;
|
|
||||||
readonly servers: ReadonlyArray<RegisteredServer>;
|
|
||||||
readonly onSelect: (server: RegisteredServer) => void;
|
|
||||||
readonly onAddServer: () => void;
|
|
||||||
readonly loading: boolean;
|
|
||||||
}, {
|
|
||||||
readonly refreshing: boolean;
|
|
||||||
}> {
|
|
||||||
// tslint:disable-next-line:no-any
|
|
||||||
public constructor(props: any) {
|
|
||||||
super(props);
|
|
||||||
this.state = {
|
|
||||||
refreshing: false,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public render(): JSX.Element {
|
|
||||||
return (
|
|
||||||
<div className="servers">
|
|
||||||
<div className="header">
|
|
||||||
<h3>Servers</h3>
|
|
||||||
<Button onClick={(): void => this.props.onAddServer()} className="add-server" type="unelevated">Add Server</Button>
|
|
||||||
<Ripple>
|
|
||||||
<div className="refresh">
|
|
||||||
<svg onClick={(): void => this.doRefresh()} className={this.state.refreshing ? "refreshing" : ""} width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlnsXlink="http://www.w3.org/1999/xlink">
|
|
||||||
<g stroke="none" strokeWidth="1" fill="none" fillRule="evenodd">
|
|
||||||
<g>
|
|
||||||
<g transform="translate(4.000000, 4.000000)" fill="#2A2E37">
|
|
||||||
<path d="M8,3 C9.179,3 10.311,3.423 11.205,4.17 L8.883,6.492 L15.094,7.031 L14.555,0.82 L12.625,2.75 C11.353,1.632 9.71,1 8,1 C4.567,1 1.664,3.454 1.097,6.834 L3.07,7.165 C3.474,4.752 5.548,3 8,3 Z" id="Path"></path>
|
|
||||||
<path d="M8,13 C6.821,13 5.689,12.577 4.795,11.83 L7.117,9.508 L0.906,8.969 L1.445,15.18 L3.375,13.25 C4.647,14.368 6.29,15 8,15 C11.433,15 14.336,12.546 14.903,9.166 L12.93,8.835 C12.526,11.248 10.452,13 8,13 Z" id="Path"></path>
|
|
||||||
</g>
|
|
||||||
<rect id="Rectangle" fillRule="nonzero" x="0" y="0" width="24" height="24"></rect>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
</Ripple>
|
|
||||||
</div>
|
|
||||||
<div className="grid">
|
|
||||||
<div className="title status">
|
|
||||||
Status
|
|
||||||
</div>
|
|
||||||
<div className="title servername">
|
|
||||||
Server Name
|
|
||||||
</div>
|
|
||||||
<div className="title hostname">
|
|
||||||
Hostname
|
|
||||||
</div>
|
|
||||||
<div className="title details">
|
|
||||||
Details
|
|
||||||
</div>
|
|
||||||
<div className="title">
|
|
||||||
{/* Used for continue/launch buttons */}
|
|
||||||
</div>
|
|
||||||
<div className="title">
|
|
||||||
{/* Used for logout and delete buttons */}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div role="progressbar" className={`mdc-linear-progress mdc-linear-progress--indeterminate ${this.props.loading ? "loading" : ""}`} ref={(d) => {
|
|
||||||
if (d) new MDCLinearProgress(d)}}>
|
|
||||||
<div className="mdc-linear-progress__buffering-dots"></div>
|
|
||||||
<div className="mdc-linear-progress__buffer"></div>
|
|
||||||
<div className="mdc-linear-progress__bar mdc-linear-progress__primary-bar">
|
|
||||||
<span className="mdc-linear-progress__bar-inner"></span>
|
|
||||||
</div>
|
|
||||||
<div className="mdc-linear-progress__bar mdc-linear-progress__secondary-bar">
|
|
||||||
<span className="mdc-linear-progress__bar-inner"></span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{this.props.servers.map((server, i) => {
|
|
||||||
return (
|
|
||||||
<Server key={server.hostname + i} user={this.props.user} server={server} onSelect={(): void => this.props.onSelect(server)} />
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private doRefresh(): void {
|
|
||||||
if (this.state.refreshing) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.setState({
|
|
||||||
refreshing: true,
|
|
||||||
}, () => {
|
|
||||||
setTimeout(() => {
|
|
||||||
this.setState({
|
|
||||||
refreshing: false,
|
|
||||||
});
|
|
||||||
}, 1500);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
interface ServerProps {
|
|
||||||
readonly user?: AuthedUser;
|
|
||||||
readonly server: RegisteredServer;
|
|
||||||
readonly onSelect: () => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class Server extends React.Component<ServerProps, {
|
|
||||||
readonly user?: AuthedUser;
|
|
||||||
readonly status: "Online" | "Offline" | "Checking";
|
|
||||||
readonly version: string;
|
|
||||||
}> {
|
|
||||||
// tslint:disable-next-line:no-any
|
|
||||||
public constructor(props: ServerProps) {
|
|
||||||
super(props);
|
|
||||||
this.state = {
|
|
||||||
status: props.server.host === "coder" ? "Online" : "Checking",
|
|
||||||
version: "",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public componentWillMount(): void {
|
|
||||||
if (this.props.server.host !== "self") {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const xhr = new XMLHttpRequest();
|
|
||||||
xhr.open("GET", this.props.server.hostname);
|
|
||||||
xhr.addEventListener("error", (err) => {
|
|
||||||
this.setState({
|
|
||||||
status: "Offline",
|
|
||||||
});
|
|
||||||
});
|
|
||||||
xhr.addEventListener("loadend", () => {
|
|
||||||
if (xhr.status === 200) {
|
|
||||||
this.setState({
|
|
||||||
status: "Online",
|
|
||||||
version: process.env.VERSION,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
this.setState({
|
|
||||||
status: "Offline",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
xhr.send();
|
|
||||||
}
|
|
||||||
|
|
||||||
public render(): JSX.Element {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<div className={`status value ${this.extraClasses}`}>
|
|
||||||
{((): JSX.Element => {
|
|
||||||
switch (this.state.status) {
|
|
||||||
case "Offline":
|
|
||||||
return (
|
|
||||||
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlnsXlink="http://www.w3.org/1999/xlink">
|
|
||||||
<g id="Artboard-Copy-3" stroke="none" strokeWidth="1" fill="none" fillRule="evenodd">
|
|
||||||
<circle id="Oval" stroke="#2B343B" strokeWidth="1.5" fillRule="nonzero" cx="8" cy="8" r="7.25"></circle>
|
|
||||||
<path d="M5.15444712,5.15444712 L10.8455529,10.8455529" id="Path-4" stroke="#2B343B" strokeWidth="1.5" fillRule="nonzero"></path>
|
|
||||||
<path d="M5.15444712,5.15444712 L10.8455529,10.8455529" id="Path-4" stroke="#2B343B" strokeWidth="1.5" fillRule="nonzero" transform="translate(8.000000, 8.000000) scale(-1, 1) translate(-8.000000, -8.000000) "></path>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
||||||
);
|
|
||||||
case "Online":
|
|
||||||
return (
|
|
||||||
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlnsXlink="http://www.w3.org/1999/xlink">
|
|
||||||
<g id="Artboard-Copy-4" stroke="none" strokeWidth="1" fill="none" fillRule="evenodd">
|
|
||||||
<g id="checkmark-copy-21" fillRule="nonzero">
|
|
||||||
<circle id="Oval" fill="#2B343B" cx="8" cy="8" r="8"></circle>
|
|
||||||
<polyline id="Path-2" stroke="#FFFFFF" strokeWidth="1.5" points="3.46296296 8.62222222 6.05555556 11.1111111 12.537037 4.88888889"></polyline>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
||||||
);
|
|
||||||
case "Checking":
|
|
||||||
return (
|
|
||||||
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlnsXlink="http://www.w3.org/1999/xlink">
|
|
||||||
<g id="Artboard-Copy-5" stroke="none" strokeWidth="1" fill="none" fillRule="evenodd">
|
|
||||||
<circle id="Oval" stroke="#2B343B" strokeWidth="1.5" fillRule="nonzero" cx="8" cy="8" r="7.25"></circle>
|
|
||||||
<polyline id="Path" stroke="#2B343B" strokeWidth="1.5" points="7.90558664 4.63916767 7.90558664 8.63916767 11.9055866 8.63916767"></polyline>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
||||||
);
|
|
||||||
default:
|
|
||||||
throw new Error("unsupported status");
|
|
||||||
}
|
|
||||||
})()}
|
|
||||||
<span>
|
|
||||||
{this.state.status}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div className={`servername value strong ${this.extraClasses}`}>
|
|
||||||
{this.props.server.host === "coder" ? (
|
|
||||||
<Logo />
|
|
||||||
) : this.props.server.name}
|
|
||||||
</div>
|
|
||||||
<div className={`hostname value ${this.extraClasses}`}>
|
|
||||||
{this.props.server.hostname}
|
|
||||||
</div>
|
|
||||||
<div className={`details value ${this.extraClasses}`}>
|
|
||||||
{this.props.server.host === "coder" && this.props.user ? `Logged in as ${this.props.user.username}` : this.state.version}
|
|
||||||
</div>
|
|
||||||
<div className={`buttons value ${this.extraClasses}`}>
|
|
||||||
<Button onClick={(): void => this.props.onSelect()} className="add-server" type="outlined">{this.props.server.host === "coder" ? "Continue" : "Launch"}</Button>
|
|
||||||
</div>
|
|
||||||
<div className={`icons value ${this.extraClasses}`}>
|
|
||||||
<Ripple>
|
|
||||||
<div>
|
|
||||||
{this.props.server.host === "coder" ? (
|
|
||||||
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlnsXlink="http://www.w3.org/1999/xlink">
|
|
||||||
<g id="Artboard" stroke="none" strokeWidth="1" fill="none" fillRule="evenodd">
|
|
||||||
<g id="log-out-copy-2" transform="translate(4.000000, 4.000000)" fill="#2A2E37">
|
|
||||||
<polygon id="Path" points="4 4 0 8 4 12 4 9 10 9 10 7 4 7"></polygon>
|
|
||||||
<path d="M15,16 L6,16 C5.4,16 5,15.6 5,15 L5,12 L7,12 L7,14 L14,14 L14,2 L7,2 L7,4 L5,4 L5,1 C5,0.4 5.4,0 6,0 L15,0 C15.6,0 16,0.4 16,1 L16,15 C16,15.6 15.6,16 15,16 Z" id="Path"></path>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
||||||
) : (
|
|
||||||
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlnsXlink="http://www.w3.org/1999/xlink">
|
|
||||||
<g id="Artboard" stroke="none" strokeWidth="1" fill="none" fillRule="evenodd">
|
|
||||||
<g id="bin" transform="translate(4.000000, 4.000000)" fill="#2B343B">
|
|
||||||
<rect id="Rectangle" x="5" y="7" width="2" height="6"></rect>
|
|
||||||
<rect id="Rectangle" x="9" y="7" width="2" height="6"></rect>
|
|
||||||
<path d="M12,1 C12,0.4 11.6,0 11,0 L5,0 C4.4,0 4,0.4 4,1 L4,3 L0,3 L0,5 L1,5 L1,15 C1,15.6 1.4,16 2,16 L14,16 C14.6,16 15,15.6 15,15 L15,5 L16,5 L16,3 L12,3 L12,1 Z M6,2 L10,2 L10,3 L6,3 L6,2 Z M13,5 L13,14 L3,14 L3,5 L13,5 Z" id="Shape" fillRule="nonzero"></path>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</Ripple>
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private get extraClasses(): string {
|
|
||||||
return this.props.server.host === "coder" ? "dark" : "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class Input extends React.Component<{
|
|
||||||
readonly label: string;
|
|
||||||
readonly id: string;
|
|
||||||
readonly type?: string;
|
|
||||||
}> {
|
|
||||||
private wrapper: HTMLDivElement | undefined;
|
|
||||||
|
|
||||||
public componentDidMount(): void {
|
|
||||||
if (this.wrapper) {
|
|
||||||
const textInput = new MDCTextField(this.wrapper);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public render(): JSX.Element {
|
|
||||||
return (
|
|
||||||
<div className="mdc-text-field mdc-text-field--outlined" ref={(i: HTMLDivElement): HTMLDivElement => this.wrapper = i}>
|
|
||||||
<input type={this.props.type || "text"} id={this.props.id} className="mdc-text-field__input" spellCheck={false}></input>
|
|
||||||
<div className="mdc-notched-outline">
|
|
||||||
<div className="mdc-notched-outline__leading"></div>
|
|
||||||
<div className="mdc-notched-outline__notch">
|
|
||||||
<label htmlFor={this.props.id} className="mdc-floating-label">{this.props.label}</label>
|
|
||||||
</div>
|
|
||||||
<div className="mdc-notched-outline__trailing"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class Button extends React.Component<{
|
|
||||||
readonly type: "outlined" | "unelevated";
|
|
||||||
readonly className?: string;
|
|
||||||
readonly onClick?: () => void;
|
|
||||||
}> {
|
|
||||||
private button: HTMLButtonElement | undefined;
|
|
||||||
|
|
||||||
public componentDidMount(): void {
|
|
||||||
if (this.button) {
|
|
||||||
const b = new MDCRipple(this.button);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public render(): JSX.Element {
|
|
||||||
return (
|
|
||||||
<button onClick={() => this.props.onClick ? this.props.onClick() : undefined} className={`mdc-button mdc-button--${this.props.type} ${this.props.className || ""}`} ref={(b: HTMLButtonElement): HTMLButtonElement => this.button = b}>
|
|
||||||
<span className="mdc-button__label">{this.props.children}</span>
|
|
||||||
</button>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class Tooltip extends React.Component<{
|
|
||||||
readonly message: string;
|
|
||||||
}> {
|
|
||||||
public componentDidMount(): void {
|
|
||||||
Object.keys(this.refs).forEach((ref) => {
|
|
||||||
const el = this.refs[ref];
|
|
||||||
if (el) {
|
|
||||||
const element = ReactDOM.findDOMNode(el);
|
|
||||||
if (element) {
|
|
||||||
const te = document.createElement("div");
|
|
||||||
te.className = "md-tooltip-content";
|
|
||||||
te.innerHTML = this.props.message;
|
|
||||||
element.appendChild(te);
|
|
||||||
(element as HTMLElement).classList.add("md-tooltip");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public render(): JSX.Element {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
{React.Children.map(this.props.children, (element, idx) => {
|
|
||||||
return React.cloneElement(element as any, { ref: idx });
|
|
||||||
})}
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class Ripple extends React.Component<{
|
|
||||||
readonly className?: string;
|
|
||||||
}> {
|
|
||||||
public componentDidMount(): void {
|
|
||||||
Object.keys(this.refs).forEach((ref) => {
|
|
||||||
const el = this.refs[ref];
|
|
||||||
if (el) {
|
|
||||||
const element = ReactDOM.findDOMNode(el);
|
|
||||||
if (element) {
|
|
||||||
(element as HTMLElement).classList.add("mdc-ripple-surface");
|
|
||||||
(element as HTMLElement).setAttribute("data-mdc-ripple-is-unbounded", "");
|
|
||||||
const r = new MDCRipple(element);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public render(): JSX.Element {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
{React.Children.map(this.props.children, (element, idx) => {
|
|
||||||
return React.cloneElement(element as any, { ref: idx });
|
|
||||||
})}
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class Logo extends React.Component {
|
|
||||||
public render(): JSX.Element {
|
|
||||||
return (
|
|
||||||
<svg className="logo" version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlnsXlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 471 117"
|
|
||||||
style={{enableBackground: "new 0 0 471 117"} as any} xmlSpace="preserve">
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<path className="logo-fill" d="M217,75.6c5.9,0,10.7-2.3,14.5-7l7.7,7.9c-6.1,6.9-13.3,10.3-21.6,10.3s-15.1-2.6-20.5-7.9
|
|
||||||
C191.7,73.7,189,67,189,59s2.7-14.7,8.2-20s12.2-8,20.1-8c8.8,0,16.2,3.4,22.2,10.1l-7.5,8.5c-3.8-4.7-8.5-7.1-14.2-7.1
|
|
||||||
c-4.5,0-8.4,1.5-11.6,4.4c-3.2,3-4.8,6.9-4.8,11.9s1.5,9,4.5,12.1C209,74.1,212.6,75.6,217,75.6z M284.1,46.7
|
|
||||||
c-3.1-3.4-6.9-5.1-11.4-5.1s-8.3,1.7-11.4,5.1s-4.6,7.5-4.6,12.3s1.5,8.9,4.6,12.3s6.9,5,11.4,5s8.3-1.7,11.4-5
|
|
||||||
c3.1-3.4,4.6-7.5,4.6-12.3S287.2,50.1,284.1,46.7z M272.7,86.8c-8,0-14.7-2.7-20.1-8s-8.2-11.9-8.2-19.9c0-7.9,2.7-14.5,8.2-19.9
|
|
||||||
c5.4-5.3,12.2-8,20.1-8c8,0,14.7,2.7,20.1,8s8.2,11.9,8.2,19.9c0,7.9-2.7,14.5-8.2,19.9C287.4,84.1,280.7,86.8,272.7,86.8z
|
|
||||||
M352.3,39.4c5.1,4.7,7.7,11.2,7.7,19.6s-2.5,15-7.5,19.9s-12.7,7.3-22.9,7.3h-18.4V32.3h19C339.8,32.4,347.2,34.7,352.3,39.4z
|
|
||||||
M343.5,71.5c3-2.8,4.4-6.8,4.4-12.1s-1.5-9.4-4.4-12.2c-3-2.9-7.5-4.3-13.6-4.3h-6.7v32.8h7.6C336.3,75.6,340.5,74.2,343.5,71.5z
|
|
||||||
M409.3,32.4v10.7h-26.8v11.1h24.1v10.3h-24.1v11.2h27.7v10.6h-39.7V32.4H409.3L409.3,32.4z M464.6,50.3c0,8.6-3.4,14.2-10.3,16.7
|
|
||||||
l13.6,19.3h-14.8l-11.9-17.2h-8.3v17.2h-12V32.4h20.4c8.4,0,14.4,1.4,17.9,4.2C462.8,39.4,464.6,44,464.6,50.3z M450.1,56.7
|
|
||||||
c1.5-1.3,2.2-3.5,2.2-6.4s-0.8-4.9-2.3-6s-4.2-1.6-8.1-1.6h-9v16h8.8C445.8,58.7,448.6,58,450.1,56.7z"/>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<path className="logo-fill" d="M164.8,50.9c-3.3,0-5.5-1.9-5.5-5.8V22.7c0-14.3-6-22.2-21.5-22.2h-7.2v15.1h2.2c6.1,0,9,3.3,9,9.2v19.8
|
|
||||||
c0,8.6,2.6,12.1,8.3,13.9c-5.7,1.7-8.3,5.3-8.3,13.9c0,4.9,0,9.8,0,14.7c0,4.1,0,8.1-1.1,12.2c-1.1,3.8-2.9,7.4-5.4,10.5
|
|
||||||
c-1.4,1.8-3,3.3-4.8,4.7v2h7.2c15.5,0,21.5-7.9,21.5-22.2V71.9c0-4,2.1-5.8,5.5-5.8h4.1V51h-4V50.9L164.8,50.9z"/>
|
|
||||||
<path className="logo-fill" d="M115.8,23.3H93.6c-0.5,0-0.9-0.4-0.9-0.9v-1.7c0-0.5,0.4-0.9,0.9-0.9h22.3c0.5,0,0.9,0.4,0.9,0.9v1.7
|
|
||||||
C116.8,22.9,116.3,23.3,115.8,23.3z"/>
|
|
||||||
<path className="logo-fill" d="M119.6,44.9h-16.2c-0.5,0-0.9-0.4-0.9-0.9v-1.7c0-0.5,0.4-0.9,0.9-0.9h16.2c0.5,0,0.9,0.4,0.9,0.9V44
|
|
||||||
C120.5,44.4,120.1,44.9,119.6,44.9z"/>
|
|
||||||
<path className="logo-fill" d="M126,34.1H93.6c-0.5,0-0.9-0.4-0.9-0.9v-1.7c0-0.5,0.4-0.9,0.9-0.9h32.3c0.5,0,0.9,0.4,0.9,0.9v1.7
|
|
||||||
C126.8,33.6,126.5,34.1,126,34.1z"/>
|
|
||||||
<g>
|
|
||||||
<path className="logo-fill" d="M67.9,28.2c2.2,0,4.4,0.2,6.5,0.7v-4.1c0-5.8,3-9.2,9-9.2h2.2V0.5h-7.2c-15.5,0-21.5,7.9-21.5,22.2v7.4
|
|
||||||
C60.4,28.9,64.1,28.2,67.9,28.2z"/>
|
|
||||||
</g>
|
|
||||||
<path className="logo-fill" d="M132.8,82.6c-1.6-12.7-11.4-23.3-24-25.7c-3.5-0.7-7-0.8-10.4-0.2c-0.1,0-0.1-0.1-0.2-0.1
|
|
||||||
c-5.5-11.5-17.3-19.1-30.1-19.1S43.6,44.9,38,56.4c-0.1,0-0.1,0.1-0.2,0.1c-3.6-0.4-7.2-0.2-10.8,0.7c-12.4,3-21.8,13.4-23.5,26
|
|
||||||
c-0.2,1.3-0.3,2.6-0.3,3.8c0,3.8,2.6,7.3,6.4,7.8c4.7,0.7,8.8-2.9,8.7-7.5c0-0.7,0-1.5,0.1-2.2c0.8-6.4,5.7-11.8,12.1-13.3
|
|
||||||
c2-0.5,4-0.6,5.9-0.3c6.1,0.8,12.1-2.3,14.7-7.7c1.9-4,4.9-7.5,8.9-9.4c4.4-2.1,9.4-2.4,14-0.8c4.8,1.7,8.4,5.3,10.6,9.8
|
|
||||||
c2.3,4.4,3.4,7.5,8.3,8.1c2,0.3,7.6,0.2,9.7,0.1c4.1,0,8.2,1.4,11.1,4.3c1.9,2,3.3,4.5,3.9,7.3c0.9,4.5-0.2,9-2.9,12.4
|
|
||||||
c-1.9,2.4-4.5,4.2-7.4,5c-1.4,0.4-2.8,0.5-4.2,0.5c-0.8,0-1.9,0-3.2,0c-4,0-12.5,0-18.9,0c-4.4,0-7.9-3.5-7.9-7.9V78.4V63.9
|
|
||||||
c0-1.2-1-2.2-2.2-2.2h-3.1c-6.1,0.1-11,6.9-11,14.1s0,26.3,0,26.3c0,7.8,6.3,14.1,14.1,14.1c0,0,34.7-0.1,35.2-0.1
|
|
||||||
c8-0.8,15.4-4.9,20.4-11.2C131.5,98.8,133.8,90.8,132.8,82.6z"/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// const $ = <K extends keyof HTMLElementTagNameMap>(tagName: K, className?: string, content?: string): HTMLElementTagNameMap[K] => {
|
|
||||||
// const el = document.createElement(tagName);
|
|
||||||
// if (className) {
|
|
||||||
// el.className = className;
|
|
||||||
// }
|
|
||||||
// if (content) {
|
|
||||||
// el.innerText = content;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// return el;
|
|
||||||
// };
|
|
||||||
|
|
||||||
// const createInput = (id: string, labelName: string, type: string = "text"): HTMLDivElement => {
|
|
||||||
// // <div class="mdc-text-field mdc-text-field--outlined">
|
|
||||||
// // <input type="password" id="password" class="mdc-text-field__input">
|
|
||||||
// // <!-- <label class="mdc-floating-label" for="name">Name</label>
|
|
||||||
// // <div class="mdc-line-ripple"></div> -->
|
|
||||||
// // <div class="mdc-notched-outline">
|
|
||||||
// // <div class="mdc-notched-outline__leading"></div>
|
|
||||||
// // <div class="mdc-notched-outline__notch">
|
|
||||||
// // <label for="password" class="mdc-floating-label">Password</label>
|
|
||||||
// // </div>
|
|
||||||
// // <div class="mdc-notched-outline__trailing"></div>
|
|
||||||
// // </div>
|
|
||||||
|
|
||||||
// const wrapper = $("div", "mdc-text-field mdc-text-field--outlined");
|
|
||||||
// const input = $("input", "mdc-text-field__input");
|
|
||||||
// input.type = type;
|
|
||||||
// input.id = id;
|
|
||||||
// wrapper.appendChild(input);
|
|
||||||
// const notchedOutline = $("div", "mdc-notched-outline");
|
|
||||||
// notchedOutline.appendChild($("div", "mdc-notched-outline__leading"));
|
|
||||||
// const notch = $("div", "mdc-notched-outline__notch");
|
|
||||||
// const label = $("label", "mdc-floating-label", labelName);
|
|
||||||
// label.setAttribute("for", id);
|
|
||||||
// notch.appendChild(label);
|
|
||||||
// notchedOutline.appendChild(notch);
|
|
||||||
// wrapper.appendChild(notchedOutline);
|
|
||||||
// wrapper.appendChild($("div", "mdc-notched-outline__trailing"));
|
|
||||||
|
|
||||||
// const field = new MDCTextField(wrapper);
|
|
||||||
|
|
||||||
// return wrapper;
|
|
||||||
// };
|
|
||||||
|
|
||||||
// export const createCoderLogin = (parentNode: HTMLElement): void => {
|
|
||||||
// parentNode.appendChild($("h1", "header", "Login with Coder"));
|
|
||||||
// parentNode.appendChild(createInput("username", "Username"));
|
|
||||||
// parentNode.appendChild($("br"));
|
|
||||||
// parentNode.appendChild($("br"));
|
|
||||||
// parentNode.appendChild(createInput("password", "Password", "password"));
|
|
||||||
// };
|
|
|
@ -1,5 +0,0 @@
|
||||||
|
|
||||||
export interface StorageProvider {
|
|
||||||
set<T>(key: string, value: T): Promise<void>;
|
|
||||||
get<T>(key: string): Promise<T | undefined>;
|
|
||||||
}
|
|
|
@ -1,24 +0,0 @@
|
||||||
.md-tooltip {
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.md-tooltip-content {
|
|
||||||
position: absolute;
|
|
||||||
bottom: -35px;
|
|
||||||
left: 50%;
|
|
||||||
padding: 7px;
|
|
||||||
transform: translateX(-50%) scale(0);
|
|
||||||
transition: transform 0.15s cubic-bezier(0, 0, 0.2, 1);
|
|
||||||
transform-origin: top;
|
|
||||||
background: rgba(67, 67, 67, 0.97);
|
|
||||||
color: white;
|
|
||||||
letter-spacing: 0.3px;
|
|
||||||
border-radius: 3px;
|
|
||||||
font-size: 12px;
|
|
||||||
font-weight: 500;
|
|
||||||
z-index: 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
.md-tooltip:hover .md-tooltip-content {
|
|
||||||
transform: translateX(-50%) scale(1);
|
|
||||||
}
|
|
|
@ -1,601 +0,0 @@
|
||||||
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
|
|
||||||
# yarn lockfile v1
|
|
||||||
|
|
||||||
|
|
||||||
"@material/animation@^0.41.0":
|
|
||||||
version "0.41.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/animation/-/animation-0.41.0.tgz#315b45b32e1aeebee8a4cf555b8ad52076d09ddd"
|
|
||||||
integrity sha512-yYAwJbX3Q2AFd4dr6IYOsWLQy2HN8zWOFVl9AbUXunjzTfJCa/ecfXCriaT6qkmoNoHeTdJHRrsQJZC5GsPvzA==
|
|
||||||
|
|
||||||
"@material/auto-init@^0.41.0":
|
|
||||||
version "0.41.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/auto-init/-/auto-init-0.41.0.tgz#8a59bb0b83e0f51ead9508074f9a29b2b6a20eec"
|
|
||||||
integrity sha512-jp6L8MpYu7DudgDfA8iTyD9BwQrYPEDsIJGbqzN9vcCBl5FoBatkB8pcFXKr+1mRBk7T1Qmf6+H5nDtxyXjHEQ==
|
|
||||||
|
|
||||||
"@material/base@^0.41.0":
|
|
||||||
version "0.41.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/base/-/base-0.41.0.tgz#badadce711b4c25b1eb889a5e7581e32cd07c421"
|
|
||||||
integrity sha512-tEyzwBRu3d1H120SfKsDVYZHcqT5lKohh/7cWKR93aAaPDkSvjpKJIjyu2yuSkjpDduVZGzVocYbOvhUKhhzXQ==
|
|
||||||
|
|
||||||
"@material/button@^0.44.0":
|
|
||||||
version "0.44.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/button/-/button-0.44.0.tgz#f01dcbea88bdc314e7640b76e5558101c8b4d69d"
|
|
||||||
integrity sha512-T8u8s8rlB49D9/5Nh5b0XsKRgSq3X0yWGo71MgaTnCnwxt8oZ6PxW/cH6Nn3Xp0NCr3mlSVQs08BviUfAmtlsg==
|
|
||||||
dependencies:
|
|
||||||
"@material/elevation" "^0.44.0"
|
|
||||||
"@material/feature-targeting" "^0.44.0"
|
|
||||||
"@material/ripple" "^0.44.0"
|
|
||||||
"@material/rtl" "^0.42.0"
|
|
||||||
"@material/shape" "^0.43.0"
|
|
||||||
"@material/theme" "^0.43.0"
|
|
||||||
"@material/typography" "^0.44.0"
|
|
||||||
|
|
||||||
"@material/card@^0.44.0":
|
|
||||||
version "0.44.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/card/-/card-0.44.0.tgz#e62050e3e77f525173a015119200055cd7b71bf0"
|
|
||||||
integrity sha512-fUixXuh133bVp5c1gPIHreL5jwMJEeVIQf0E4xdxhkA+i4ku8fIAvIW62EuCmfJsXicv4q8NG3Ip6pCY+NW3ZA==
|
|
||||||
dependencies:
|
|
||||||
"@material/elevation" "^0.44.0"
|
|
||||||
"@material/ripple" "^0.44.0"
|
|
||||||
"@material/rtl" "^0.42.0"
|
|
||||||
"@material/shape" "^0.43.0"
|
|
||||||
"@material/theme" "^0.43.0"
|
|
||||||
|
|
||||||
"@material/checkbox@^0.44.0":
|
|
||||||
version "0.44.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/checkbox/-/checkbox-0.44.0.tgz#5d0eee1db006db9f0fb700bf1c20408292305cf7"
|
|
||||||
integrity sha512-IzucxG+NuPNyByGmHg/cuYJ5ooMKouuj994PZXZyqb7owfrjjtXm7wjav66cvCowbVbcoa1owQMGBi18C9f4TQ==
|
|
||||||
dependencies:
|
|
||||||
"@material/animation" "^0.41.0"
|
|
||||||
"@material/base" "^0.41.0"
|
|
||||||
"@material/ripple" "^0.44.0"
|
|
||||||
"@material/rtl" "^0.42.0"
|
|
||||||
"@material/selection-control" "^0.44.0"
|
|
||||||
"@material/theme" "^0.43.0"
|
|
||||||
|
|
||||||
"@material/chips@^0.44.0":
|
|
||||||
version "0.44.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/chips/-/chips-0.44.0.tgz#bf553a5bf5db7320978402ac92069c9688b84d5a"
|
|
||||||
integrity sha512-+qrme6sGwYmX/ixHAo3Z1M7lorsxRyKexn1l+BSBX5PBc2f4w5Ml1eYYYcyVGfLX9LXmefRk0G6dUXXPyCE00g==
|
|
||||||
dependencies:
|
|
||||||
"@material/animation" "^0.41.0"
|
|
||||||
"@material/base" "^0.41.0"
|
|
||||||
"@material/checkbox" "^0.44.0"
|
|
||||||
"@material/elevation" "^0.44.0"
|
|
||||||
"@material/ripple" "^0.44.0"
|
|
||||||
"@material/shape" "^0.43.0"
|
|
||||||
"@material/theme" "^0.43.0"
|
|
||||||
"@material/typography" "^0.44.0"
|
|
||||||
|
|
||||||
"@material/dialog@^0.44.0":
|
|
||||||
version "0.44.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/dialog/-/dialog-0.44.0.tgz#388f93f9f225824c75cbe9da8c464a52d79972e8"
|
|
||||||
integrity sha512-V6ButfknOMKOscL0Y39yLjamxvrIuyugobjf5s44ZeJc+9jUSkC7M3zP+T7rh358NcX+JSPP8iCGmUn/+LXpMQ==
|
|
||||||
dependencies:
|
|
||||||
"@material/animation" "^0.41.0"
|
|
||||||
"@material/base" "^0.41.0"
|
|
||||||
"@material/dom" "^0.41.0"
|
|
||||||
"@material/elevation" "^0.44.0"
|
|
||||||
"@material/ripple" "^0.44.0"
|
|
||||||
"@material/rtl" "^0.42.0"
|
|
||||||
"@material/shape" "^0.43.0"
|
|
||||||
"@material/theme" "^0.43.0"
|
|
||||||
"@material/typography" "^0.44.0"
|
|
||||||
focus-trap "^4.0.2"
|
|
||||||
|
|
||||||
"@material/dom@^0.41.0":
|
|
||||||
version "0.41.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/dom/-/dom-0.41.0.tgz#6756865f97bad4c91ee75e69d769d7cdc25398ae"
|
|
||||||
integrity sha512-wOJrMwjPddYXpQFZAIaCLWI3TO/6KU1lxESTBzunni8A4FHQVWhokml5Xt85GqZwmPFeIF2s+D0wfbWyrGBuKQ==
|
|
||||||
|
|
||||||
"@material/drawer@^0.44.0":
|
|
||||||
version "0.44.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/drawer/-/drawer-0.44.0.tgz#74b3ddfb741bffc72331c7a73cf62716fd3f0ab3"
|
|
||||||
integrity sha512-AYwFe0jgqqSmJd1bny8JJTA2SScF86Wfbk99lXXEwd/acS8IbnnuH6zfAg6MyJX12FDb8dE8Z/Ok1IwLiVa9sQ==
|
|
||||||
dependencies:
|
|
||||||
"@material/animation" "^0.41.0"
|
|
||||||
"@material/base" "^0.41.0"
|
|
||||||
"@material/elevation" "^0.44.0"
|
|
||||||
"@material/list" "^0.44.0"
|
|
||||||
"@material/ripple" "^0.44.0"
|
|
||||||
"@material/rtl" "^0.42.0"
|
|
||||||
"@material/shape" "^0.43.0"
|
|
||||||
"@material/theme" "^0.43.0"
|
|
||||||
"@material/typography" "^0.44.0"
|
|
||||||
focus-trap "^4.0.2"
|
|
||||||
|
|
||||||
"@material/elevation@^0.44.0":
|
|
||||||
version "0.44.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/elevation/-/elevation-0.44.0.tgz#ca16a67188ce9810dc2fa3d7a39073e72df4b754"
|
|
||||||
integrity sha512-edNou34yFCSMb6XXe/6Y7AEh8DigWAhBUyIeMiMBD4k1km2xYCJbcnl8FBPJFteOrca97KoJComRlJPB6EurRQ==
|
|
||||||
dependencies:
|
|
||||||
"@material/animation" "^0.41.0"
|
|
||||||
"@material/theme" "^0.43.0"
|
|
||||||
|
|
||||||
"@material/fab@^0.44.0":
|
|
||||||
version "0.44.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/fab/-/fab-0.44.0.tgz#0bcbbdfb6f24c53d59e08c9c0d400d2616dea184"
|
|
||||||
integrity sha512-1CEP4NlXDYioJ/YpSjh/MlIygtoC7CaHqIbucxX1O5WRPmS7K1uPt+o7netbLErAmcJdV/JrI/tqh9kKuX2x/Q==
|
|
||||||
dependencies:
|
|
||||||
"@material/animation" "^0.41.0"
|
|
||||||
"@material/elevation" "^0.44.0"
|
|
||||||
"@material/ripple" "^0.44.0"
|
|
||||||
"@material/rtl" "^0.42.0"
|
|
||||||
"@material/shape" "^0.43.0"
|
|
||||||
"@material/theme" "^0.43.0"
|
|
||||||
"@material/typography" "^0.44.0"
|
|
||||||
|
|
||||||
"@material/feature-targeting@^0.44.0":
|
|
||||||
version "0.44.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/feature-targeting/-/feature-targeting-0.44.0.tgz#52cc73f0c8a83159de0357aebe74f15f9856fb4c"
|
|
||||||
integrity sha512-ShuC2TOLfjFpYUCQFtvkqDJhM6HTaucSx5HkRbOvOG+VlpzDx6pAqRUmdVaq2p7tHoQf2vwPMlSVm3gOjWt4VQ==
|
|
||||||
|
|
||||||
"@material/floating-label@^0.44.0":
|
|
||||||
version "0.44.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/floating-label/-/floating-label-0.44.0.tgz#8694cd49f6905641b67a9e7a112b820d028f09c7"
|
|
||||||
integrity sha512-k4npGNxyMtnjgJZNjU5VvqqaUqlbzlbVAhepT8PxYTpj+4Skg6PjHwieTCDCgsbqHvFcQX+WfUrSZXY7wFV7cw==
|
|
||||||
dependencies:
|
|
||||||
"@material/animation" "^0.41.0"
|
|
||||||
"@material/base" "^0.41.0"
|
|
||||||
"@material/rtl" "^0.42.0"
|
|
||||||
"@material/theme" "^0.43.0"
|
|
||||||
"@material/typography" "^0.44.0"
|
|
||||||
|
|
||||||
"@material/form-field@^0.44.0":
|
|
||||||
version "0.44.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/form-field/-/form-field-0.44.0.tgz#b7518e885c0e953a2a5fe0140af927c30e066f4e"
|
|
||||||
integrity sha512-SK+V34dzoBCQ/CHn5nBp8BAh21Vj9p1pcok+/WpYBTeg4EphTYP2nUQLMNEN92l6zjgAYf+g9Ocj3t26HNHWqA==
|
|
||||||
dependencies:
|
|
||||||
"@material/base" "^0.41.0"
|
|
||||||
"@material/rtl" "^0.42.0"
|
|
||||||
"@material/selection-control" "^0.44.0"
|
|
||||||
"@material/theme" "^0.43.0"
|
|
||||||
"@material/typography" "^0.44.0"
|
|
||||||
|
|
||||||
"@material/grid-list@^0.44.0":
|
|
||||||
version "0.44.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/grid-list/-/grid-list-0.44.0.tgz#bd31d992ab1a910731e4a47c11fe91d44e3bc02b"
|
|
||||||
integrity sha512-NxLL0A48K1O14ZZymFIyf6HDbF33+NgXYXqP2yosTC3Jw4iwmUcJTpFTmSw1U/m1xT4zEpeKEGJ4vjVUWpS9Mg==
|
|
||||||
dependencies:
|
|
||||||
"@material/base" "^0.41.0"
|
|
||||||
"@material/rtl" "^0.42.0"
|
|
||||||
"@material/theme" "^0.43.0"
|
|
||||||
"@material/typography" "^0.44.0"
|
|
||||||
|
|
||||||
"@material/icon-button@^0.44.0":
|
|
||||||
version "0.44.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/icon-button/-/icon-button-0.44.0.tgz#febbcfd27d91eca8096ae042b9c07ed0f65345e9"
|
|
||||||
integrity sha512-n6L7RaRyEci6eGsuBTSEG+t9ATHAHaMlf9zuTWorEnIXY4DAmGO7ggBjw4+1XIOjhpLeIjyJdcvUK6Yz/UVM6Q==
|
|
||||||
dependencies:
|
|
||||||
"@material/base" "^0.41.0"
|
|
||||||
"@material/ripple" "^0.44.0"
|
|
||||||
"@material/theme" "^0.43.0"
|
|
||||||
|
|
||||||
"@material/icon-toggle@^0.44.0":
|
|
||||||
version "0.44.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/icon-toggle/-/icon-toggle-0.44.0.tgz#b9de32f194b5aa9721ca799d59be0f477a5c5305"
|
|
||||||
integrity sha512-8T1b4iK61/q/3U0iIjEDJ9do5viCQ45IbrQqa8EYCZ1KDU/Q8z5N+bvOzQK8XnTL51BdDRMgP9lfQZh6nszmkA==
|
|
||||||
dependencies:
|
|
||||||
"@material/animation" "^0.41.0"
|
|
||||||
"@material/base" "^0.41.0"
|
|
||||||
"@material/ripple" "^0.44.0"
|
|
||||||
"@material/theme" "^0.43.0"
|
|
||||||
|
|
||||||
"@material/image-list@^0.44.0":
|
|
||||||
version "0.44.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/image-list/-/image-list-0.44.0.tgz#a27996962044ac8c9ce6cb509f63746f08ed2e98"
|
|
||||||
integrity sha512-kI9aKJdc1Bd02l8nRTGG1wy/lNkECScfnBmCiLQ3XjAFtRYd2eWO0Z/AVvUG3egsIZnZBxqFGGsf5Htm9E/HiQ==
|
|
||||||
dependencies:
|
|
||||||
"@material/shape" "^0.43.0"
|
|
||||||
"@material/theme" "^0.43.0"
|
|
||||||
"@material/typography" "^0.44.0"
|
|
||||||
|
|
||||||
"@material/layout-grid@^0.41.0":
|
|
||||||
version "0.41.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/layout-grid/-/layout-grid-0.41.0.tgz#2e7d3be76313e0684d573b10c2c6a88b3230d251"
|
|
||||||
integrity sha512-Sa5RNoTGgfIojqJ9E94p7/k11V6q/tGk7HwKi4AQNAPjxield0zcl3G/SbsSb8YSHoK+D+7OXDN+n11x6EqF7g==
|
|
||||||
|
|
||||||
"@material/line-ripple@^0.43.0":
|
|
||||||
version "0.43.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/line-ripple/-/line-ripple-0.43.0.tgz#6cb530bab53f055f3583646a21ad20c1703f3a83"
|
|
||||||
integrity sha512-sXZYW4Em5uLEnAuVsQCO+sVHsTg7J2TOTJ0+akwZFMmd2tmNicjarQdlGIE9iU7Wjm51NOoLAu6Mz+8kLg90bQ==
|
|
||||||
dependencies:
|
|
||||||
"@material/animation" "^0.41.0"
|
|
||||||
"@material/base" "^0.41.0"
|
|
||||||
"@material/theme" "^0.43.0"
|
|
||||||
|
|
||||||
"@material/linear-progress@^0.43.0":
|
|
||||||
version "0.43.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/linear-progress/-/linear-progress-0.43.0.tgz#4821424aa24c78de256e74a91d5be3df55c534d9"
|
|
||||||
integrity sha512-bqkDcob+xp1mFkyBsOkoaLgrtapmz7jznGoI3nmkqyk75EB2XQcn1H8Vr6cnp/jkF4nbKu0GdVJO3VXUFmGmrQ==
|
|
||||||
dependencies:
|
|
||||||
"@material/animation" "^0.41.0"
|
|
||||||
"@material/base" "^0.41.0"
|
|
||||||
"@material/theme" "^0.43.0"
|
|
||||||
|
|
||||||
"@material/list@^0.44.0":
|
|
||||||
version "0.44.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/list/-/list-0.44.0.tgz#cf1910e15b66759334b8618d1110fbcc72c3d326"
|
|
||||||
integrity sha512-35gkN1+XZaau9d9ngyN2x14bzkj/ajZCDm7mbWibDQy272A16j6KuFLQFA8RUQV04OgL4YPVxY87dpCn/p+uTg==
|
|
||||||
dependencies:
|
|
||||||
"@material/base" "^0.41.0"
|
|
||||||
"@material/dom" "^0.41.0"
|
|
||||||
"@material/ripple" "^0.44.0"
|
|
||||||
"@material/rtl" "^0.42.0"
|
|
||||||
"@material/shape" "^0.43.0"
|
|
||||||
"@material/theme" "^0.43.0"
|
|
||||||
"@material/typography" "^0.44.0"
|
|
||||||
|
|
||||||
"@material/menu-surface@^0.44.0":
|
|
||||||
version "0.44.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/menu-surface/-/menu-surface-0.44.0.tgz#902c081df42859b925a5b4502791b3febf48f1ae"
|
|
||||||
integrity sha512-s49kvIlQ4H5wvMD4yeHMMqnamPod06IUagMK6Ry0oTpUANSnyeNXxa3HkScl7DMJiS8IJeV21fSLAzlZYP2PDQ==
|
|
||||||
dependencies:
|
|
||||||
"@material/animation" "^0.41.0"
|
|
||||||
"@material/base" "^0.41.0"
|
|
||||||
"@material/elevation" "^0.44.0"
|
|
||||||
"@material/rtl" "^0.42.0"
|
|
||||||
"@material/shape" "^0.43.0"
|
|
||||||
"@material/theme" "^0.43.0"
|
|
||||||
|
|
||||||
"@material/menu@^0.44.0":
|
|
||||||
version "0.44.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/menu/-/menu-0.44.0.tgz#776ec8a04406266a0a0a13eb140b1fd691e442cb"
|
|
||||||
integrity sha512-92XvAcv9rBW1jQ3UvwJ8zk9hbSRe/FqSuFdZ9fNPE348dCY2pbcdQfnUJTe3ycAN/I1c5frkrhx8F0II+nfbNQ==
|
|
||||||
dependencies:
|
|
||||||
"@material/base" "^0.41.0"
|
|
||||||
"@material/list" "^0.44.0"
|
|
||||||
"@material/menu-surface" "^0.44.0"
|
|
||||||
"@material/ripple" "^0.44.0"
|
|
||||||
"@material/rtl" "^0.42.0"
|
|
||||||
|
|
||||||
"@material/notched-outline@^0.44.0":
|
|
||||||
version "0.44.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/notched-outline/-/notched-outline-0.44.0.tgz#d5a2e1d649921575a7cd2e88ee4581e4a1809573"
|
|
||||||
integrity sha512-c3nqOqUQAmW3h4zBbZVbMRdf4nNTYm0tVwXIAwmcCs5nvAthEHnzHwwFddNP7/9Wju6LZ0uqWn6xlyKly0uipw==
|
|
||||||
dependencies:
|
|
||||||
"@material/animation" "^0.41.0"
|
|
||||||
"@material/base" "^0.41.0"
|
|
||||||
"@material/floating-label" "^0.44.0"
|
|
||||||
"@material/rtl" "^0.42.0"
|
|
||||||
"@material/shape" "^0.43.0"
|
|
||||||
"@material/theme" "^0.43.0"
|
|
||||||
|
|
||||||
"@material/radio@^0.44.0":
|
|
||||||
version "0.44.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/radio/-/radio-0.44.0.tgz#f4cacdfabc7d765aa000cb34c5a37966f6d4fd6d"
|
|
||||||
integrity sha512-ar7uhlfHuSwM9JUUjpv7pLDLE0p436cCMxNTpmMjWabfvo3pMWlExvk72Oj81tBgfxY/uASLB3oj4neudXu9JQ==
|
|
||||||
dependencies:
|
|
||||||
"@material/animation" "^0.41.0"
|
|
||||||
"@material/base" "^0.41.0"
|
|
||||||
"@material/ripple" "^0.44.0"
|
|
||||||
"@material/selection-control" "^0.44.0"
|
|
||||||
"@material/theme" "^0.43.0"
|
|
||||||
|
|
||||||
"@material/ripple@^0.44.0":
|
|
||||||
version "0.44.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/ripple/-/ripple-0.44.0.tgz#98920ff8ec4bf5714c97df3d190f02f8a5b476cc"
|
|
||||||
integrity sha512-MlaW4nUDgzS0JOBfsUawXyTOilr0jn+xvTVn6PEaGh2rmhNA54AhixXvdsVUWE9lfmHAsZV0AJHz2z7nunNhbQ==
|
|
||||||
dependencies:
|
|
||||||
"@material/animation" "^0.41.0"
|
|
||||||
"@material/base" "^0.41.0"
|
|
||||||
"@material/feature-targeting" "^0.44.0"
|
|
||||||
"@material/theme" "^0.43.0"
|
|
||||||
|
|
||||||
"@material/rtl@^0.42.0":
|
|
||||||
version "0.42.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/rtl/-/rtl-0.42.0.tgz#1836e78186c2d8b996f6fbf97adab203535335bc"
|
|
||||||
integrity sha512-VrnrKJzhmspsN8WXHuxxBZ69yM5IwhCUqWr1t1eNfw3ZEvEj7i1g3P31HGowKThIN1dc1Wh4LE14rCISWCtv5w==
|
|
||||||
|
|
||||||
"@material/select@^0.44.0":
|
|
||||||
version "0.44.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/select/-/select-0.44.0.tgz#8041b4fe6247d013b0f12685fbdf50aa9ff57b35"
|
|
||||||
integrity sha512-tw3/QIBLuRCT+5IXx4IPiJk7FzeGeR65JEizdRUItH8yzoIiQLs/b2i3KtHM2YBXHgeUcEBF2AOqPX2opdYhug==
|
|
||||||
dependencies:
|
|
||||||
"@material/animation" "^0.41.0"
|
|
||||||
"@material/base" "^0.41.0"
|
|
||||||
"@material/floating-label" "^0.44.0"
|
|
||||||
"@material/line-ripple" "^0.43.0"
|
|
||||||
"@material/menu" "^0.44.0"
|
|
||||||
"@material/menu-surface" "^0.44.0"
|
|
||||||
"@material/notched-outline" "^0.44.0"
|
|
||||||
"@material/ripple" "^0.44.0"
|
|
||||||
"@material/rtl" "^0.42.0"
|
|
||||||
"@material/shape" "^0.43.0"
|
|
||||||
"@material/theme" "^0.43.0"
|
|
||||||
"@material/typography" "^0.44.0"
|
|
||||||
|
|
||||||
"@material/selection-control@^0.44.0":
|
|
||||||
version "0.44.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/selection-control/-/selection-control-0.44.0.tgz#63d5c65a47a9f54f5a0316b5ecdb5e5f35108609"
|
|
||||||
integrity sha512-HgCAPnMVMEj4X4ILkFSifqtZ3Tcc5HkU+Lfk9g0807sCaN/qBKWkYKLH2WJUbW8uk+MXK7DgP1khtS5zzanJWA==
|
|
||||||
dependencies:
|
|
||||||
"@material/ripple" "^0.44.0"
|
|
||||||
|
|
||||||
"@material/shape@^0.43.0":
|
|
||||||
version "0.43.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/shape/-/shape-0.43.0.tgz#b877acfd8be8abc9ddcf6601eb60dd0588292415"
|
|
||||||
integrity sha512-KGnoQV4G2OQbMe5Lr5Xbk8XNlO93Qi/juxXtd2wrAfiaPmktD8ug0CwdVDOPBOmj9a0gX3Ofi9XWcoU+tLEVjg==
|
|
||||||
|
|
||||||
"@material/slider@^0.44.0":
|
|
||||||
version "0.44.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/slider/-/slider-0.44.0.tgz#2055df894eb725e541cde50a544719c07934755b"
|
|
||||||
integrity sha512-Lnn2fdUesXX4O0UpJzveEuOj+og+dXCwhal73u3l3NXEdc/eRgYxwWdF3ww4MmCZ786EwUmjb4vIc9olN4DO3A==
|
|
||||||
dependencies:
|
|
||||||
"@material/animation" "^0.41.0"
|
|
||||||
"@material/base" "^0.41.0"
|
|
||||||
"@material/rtl" "^0.42.0"
|
|
||||||
"@material/theme" "^0.43.0"
|
|
||||||
"@material/typography" "^0.44.0"
|
|
||||||
|
|
||||||
"@material/snackbar@^0.44.0":
|
|
||||||
version "0.44.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/snackbar/-/snackbar-0.44.0.tgz#d98672b849f5f295e4fac2d474a9c80f11945518"
|
|
||||||
integrity sha512-KhCrmJm8Zu/ZZPuRCGfMKsZ0vudINlNgTjlOau0kQ/UgR1xBUvLOE8NjyXZr0RQz5obyW7xpyIWIpscn0IUeyw==
|
|
||||||
dependencies:
|
|
||||||
"@material/animation" "^0.41.0"
|
|
||||||
"@material/base" "^0.41.0"
|
|
||||||
"@material/button" "^0.44.0"
|
|
||||||
"@material/dom" "^0.41.0"
|
|
||||||
"@material/icon-button" "^0.44.0"
|
|
||||||
"@material/ripple" "^0.44.0"
|
|
||||||
"@material/rtl" "^0.42.0"
|
|
||||||
"@material/shape" "^0.43.0"
|
|
||||||
"@material/theme" "^0.43.0"
|
|
||||||
"@material/typography" "^0.44.0"
|
|
||||||
|
|
||||||
"@material/switch@^0.44.0":
|
|
||||||
version "0.44.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/switch/-/switch-0.44.0.tgz#f2cbb447437b12eb3bc7f0ec8318dbd3b4f0afce"
|
|
||||||
integrity sha512-EadCg6lHUF260R2Q/l++vXIITqacvbXlobSoewA5ib6y9BU2g7l13wL1W8xAVJNUMgFa/PyN+EKT3oCql7jZLg==
|
|
||||||
dependencies:
|
|
||||||
"@material/animation" "^0.41.0"
|
|
||||||
"@material/base" "^0.41.0"
|
|
||||||
"@material/elevation" "^0.44.0"
|
|
||||||
"@material/ripple" "^0.44.0"
|
|
||||||
"@material/rtl" "^0.42.0"
|
|
||||||
"@material/selection-control" "^0.44.0"
|
|
||||||
"@material/theme" "^0.43.0"
|
|
||||||
|
|
||||||
"@material/tab-bar@^0.44.0":
|
|
||||||
version "0.44.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/tab-bar/-/tab-bar-0.44.0.tgz#b17d791bd557b1d84892fef1a1d8b8d6fef7c6d6"
|
|
||||||
integrity sha512-kCrt05d61YXyY43SNc0dPGuqysbcLr/KRDBvzpXgE4gv2jCCVhhjAH10KPlx8pthp/UtvrYJHb34acAKEGzdHA==
|
|
||||||
dependencies:
|
|
||||||
"@material/base" "^0.41.0"
|
|
||||||
"@material/elevation" "^0.44.0"
|
|
||||||
"@material/tab" "^0.44.0"
|
|
||||||
"@material/tab-scroller" "^0.44.0"
|
|
||||||
|
|
||||||
"@material/tab-indicator@^0.43.0":
|
|
||||||
version "0.43.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/tab-indicator/-/tab-indicator-0.43.0.tgz#37fd05513ba55ae218d9068c986c2676096fd6eb"
|
|
||||||
integrity sha512-RMNMQpWYghWpM6d0ayfuHEPzTiebKG0bMthViiD6tly8PubmOT8mShNhPm8ihybhDPUOLSz+7V4QNE5wikLEYg==
|
|
||||||
dependencies:
|
|
||||||
"@material/animation" "^0.41.0"
|
|
||||||
"@material/base" "^0.41.0"
|
|
||||||
"@material/theme" "^0.43.0"
|
|
||||||
|
|
||||||
"@material/tab-scroller@^0.44.0":
|
|
||||||
version "0.44.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/tab-scroller/-/tab-scroller-0.44.0.tgz#82d092ed45d2ee9d82038bed318e6ff6bdc36dad"
|
|
||||||
integrity sha512-Ufd3NWBN11kY2oA7bGmTYWGP1uz2mq0tfDM0JOiqoLMgD7y3Z18kmxnpq2qkg1vi4kvix28hBYGGMfLlq9rGDA==
|
|
||||||
dependencies:
|
|
||||||
"@material/animation" "^0.41.0"
|
|
||||||
"@material/base" "^0.41.0"
|
|
||||||
"@material/tab" "^0.44.0"
|
|
||||||
|
|
||||||
"@material/tab@^0.44.0":
|
|
||||||
version "0.44.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/tab/-/tab-0.44.0.tgz#254b92cff99015f0bd59a86d08d3f1c4744d0742"
|
|
||||||
integrity sha512-czrbGjtKkmUS3iYBX523xT5GOkjP0h+0x9fTnw+heFNpw5dCn6cZvlj3D9ayZU+ZH93x68TFhFVBuLU5f0EBXw==
|
|
||||||
dependencies:
|
|
||||||
"@material/base" "^0.41.0"
|
|
||||||
"@material/ripple" "^0.44.0"
|
|
||||||
"@material/rtl" "^0.42.0"
|
|
||||||
"@material/tab-indicator" "^0.43.0"
|
|
||||||
"@material/theme" "^0.43.0"
|
|
||||||
"@material/typography" "^0.44.0"
|
|
||||||
|
|
||||||
"@material/textfield@^0.44.0":
|
|
||||||
version "0.44.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/textfield/-/textfield-0.44.0.tgz#277b33948ddff33f7f643323895e5a683f013601"
|
|
||||||
integrity sha512-IMBwMcE82eVU+Wifpu0t84tozvBPLCeqQELDtZNYujKg3RxaultzJLwIyGKPMZ9R4yPEpV2vgXPGKE+2/AWt0g==
|
|
||||||
dependencies:
|
|
||||||
"@material/animation" "^0.41.0"
|
|
||||||
"@material/base" "^0.41.0"
|
|
||||||
"@material/floating-label" "^0.44.0"
|
|
||||||
"@material/line-ripple" "^0.43.0"
|
|
||||||
"@material/notched-outline" "^0.44.0"
|
|
||||||
"@material/ripple" "^0.44.0"
|
|
||||||
"@material/rtl" "^0.42.0"
|
|
||||||
"@material/shape" "^0.43.0"
|
|
||||||
"@material/theme" "^0.43.0"
|
|
||||||
"@material/typography" "^0.44.0"
|
|
||||||
|
|
||||||
"@material/theme@^0.43.0":
|
|
||||||
version "0.43.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/theme/-/theme-0.43.0.tgz#6d9fa113c82e841817882172c152d60d2d203ca6"
|
|
||||||
integrity sha512-/zndZL6EihI18v2mYd4O8xvOBAAXmLeHyHVK28LozSAaJ9okQgD25wq5Ktk95oMTmPIC+rH66KcK6371ivNk8g==
|
|
||||||
|
|
||||||
"@material/toolbar@^0.44.0":
|
|
||||||
version "0.44.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/toolbar/-/toolbar-0.44.0.tgz#6689aecdeccc78b7a890a3abbe8b68a2c6339307"
|
|
||||||
integrity sha512-YgLlOFQ5VzFLQBpXYSMviEbYox0fia+sasHuYPUhTAtas1ExVt9EEiIolDSVvhv2PruTReKKefxSbXAqGlOHog==
|
|
||||||
dependencies:
|
|
||||||
"@material/base" "^0.41.0"
|
|
||||||
"@material/elevation" "^0.44.0"
|
|
||||||
"@material/ripple" "^0.44.0"
|
|
||||||
"@material/rtl" "^0.42.0"
|
|
||||||
"@material/theme" "^0.43.0"
|
|
||||||
"@material/typography" "^0.44.0"
|
|
||||||
|
|
||||||
"@material/top-app-bar@^0.44.0":
|
|
||||||
version "0.44.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/top-app-bar/-/top-app-bar-0.44.0.tgz#2495c7f9567568fb961ccced24f479c4806a72af"
|
|
||||||
integrity sha512-tf0yXQJARYs8UPaH8oo3LnsSHEiur7Zm8Fc3hv3F0gNRRaZYBjwsMQMVbZZaWoQCWskMALyntBg+Fo18zdgDxw==
|
|
||||||
dependencies:
|
|
||||||
"@material/animation" "^0.41.0"
|
|
||||||
"@material/base" "^0.41.0"
|
|
||||||
"@material/elevation" "^0.44.0"
|
|
||||||
"@material/ripple" "^0.44.0"
|
|
||||||
"@material/rtl" "^0.42.0"
|
|
||||||
"@material/shape" "^0.43.0"
|
|
||||||
"@material/theme" "^0.43.0"
|
|
||||||
"@material/typography" "^0.44.0"
|
|
||||||
|
|
||||||
"@material/typography@^0.44.0":
|
|
||||||
version "0.44.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@material/typography/-/typography-0.44.0.tgz#cf61dce2ee89bfa084d86e1b0f270a585bf9dfaf"
|
|
||||||
integrity sha512-m4SjA9OjZRDKowN3cPzEa8e2GlTlEn3ZmW/Fy9eRNSp83iY+8a0xl6kCaF80v5qAVwVcpfEFyEHWxMJtkBw2uA==
|
|
||||||
|
|
||||||
"@types/prop-types@*":
|
|
||||||
version "15.5.8"
|
|
||||||
resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.5.8.tgz#8ae4e0ea205fe95c3901a5a1df7f66495e3a56ce"
|
|
||||||
integrity sha512-3AQoUxQcQtLHsK25wtTWIoIpgYjH3vSDroZOUr7PpCHw/jLY1RB9z9E8dBT/OSmwStVgkRNvdh+ZHNiomRieaw==
|
|
||||||
|
|
||||||
"@types/react-dom@^16.8.0":
|
|
||||||
version "16.8.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-16.8.0.tgz#c565f43f9d2ec911f9e0b8f3b74e25e67879aa3f"
|
|
||||||
integrity sha512-Jp4ufcEEjVJEB0OHq2MCZcE1u3KYUKO6WnSuiU/tZeYeiZxUoQavfa/TZeiIT+1XoN6l0lQVNM30VINZFDeolQ==
|
|
||||||
dependencies:
|
|
||||||
"@types/react" "*"
|
|
||||||
|
|
||||||
"@types/react@*", "@types/react@^16.8.2":
|
|
||||||
version "16.8.2"
|
|
||||||
resolved "https://registry.yarnpkg.com/@types/react/-/react-16.8.2.tgz#3b7a7f7ea89d1c7d68b00849fb5de839011c077b"
|
|
||||||
integrity sha512-6mcKsqlqkN9xADrwiUz2gm9Wg4iGnlVGciwBRYFQSMWG6MQjhOZ/AVnxn+6v8nslFgfYTV8fNdE6XwKu6va5PA==
|
|
||||||
dependencies:
|
|
||||||
"@types/prop-types" "*"
|
|
||||||
csstype "^2.2.0"
|
|
||||||
|
|
||||||
csstype@^2.2.0:
|
|
||||||
version "2.6.2"
|
|
||||||
resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.2.tgz#3043d5e065454579afc7478a18de41909c8a2f01"
|
|
||||||
integrity sha512-Rl7PvTae0pflc1YtxtKbiSqq20Ts6vpIYOD5WBafl4y123DyHUeLrRdQP66sQW8/6gmX8jrYJLXwNeMqYVJcow==
|
|
||||||
|
|
||||||
focus-trap@^4.0.2:
|
|
||||||
version "4.0.2"
|
|
||||||
resolved "https://registry.yarnpkg.com/focus-trap/-/focus-trap-4.0.2.tgz#4ee2b96547c9ea0e4252a2d4b2cca68944194663"
|
|
||||||
integrity sha512-HtLjfAK7Hp2qbBtLS6wEznID1mPT+48ZnP2nkHzgjpL4kroYHg0CdqJ5cTXk+UO5znAxF5fRUkhdyfgrhh8Lzw==
|
|
||||||
dependencies:
|
|
||||||
tabbable "^3.1.2"
|
|
||||||
xtend "^4.0.1"
|
|
||||||
|
|
||||||
"js-tokens@^3.0.0 || ^4.0.0":
|
|
||||||
version "4.0.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
|
|
||||||
integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
|
|
||||||
|
|
||||||
loose-envify@^1.1.0:
|
|
||||||
version "1.4.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
|
|
||||||
integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==
|
|
||||||
dependencies:
|
|
||||||
js-tokens "^3.0.0 || ^4.0.0"
|
|
||||||
|
|
||||||
material-components-web@^0.44.0:
|
|
||||||
version "0.44.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/material-components-web/-/material-components-web-0.44.0.tgz#ff782e8d7bdd8212d3c6022a731258d0d42da531"
|
|
||||||
integrity sha512-BSRLf58SMVhAvlDhJDlcgYuvzeMwbMHKTJ7oIB8LaM24ZpXBxP9XCYJpKheMtiVLrgllCGDlJ/47OIDReHQXdQ==
|
|
||||||
dependencies:
|
|
||||||
"@material/animation" "^0.41.0"
|
|
||||||
"@material/auto-init" "^0.41.0"
|
|
||||||
"@material/base" "^0.41.0"
|
|
||||||
"@material/button" "^0.44.0"
|
|
||||||
"@material/card" "^0.44.0"
|
|
||||||
"@material/checkbox" "^0.44.0"
|
|
||||||
"@material/chips" "^0.44.0"
|
|
||||||
"@material/dialog" "^0.44.0"
|
|
||||||
"@material/dom" "^0.41.0"
|
|
||||||
"@material/drawer" "^0.44.0"
|
|
||||||
"@material/elevation" "^0.44.0"
|
|
||||||
"@material/fab" "^0.44.0"
|
|
||||||
"@material/feature-targeting" "^0.44.0"
|
|
||||||
"@material/floating-label" "^0.44.0"
|
|
||||||
"@material/form-field" "^0.44.0"
|
|
||||||
"@material/grid-list" "^0.44.0"
|
|
||||||
"@material/icon-button" "^0.44.0"
|
|
||||||
"@material/icon-toggle" "^0.44.0"
|
|
||||||
"@material/image-list" "^0.44.0"
|
|
||||||
"@material/layout-grid" "^0.41.0"
|
|
||||||
"@material/line-ripple" "^0.43.0"
|
|
||||||
"@material/linear-progress" "^0.43.0"
|
|
||||||
"@material/list" "^0.44.0"
|
|
||||||
"@material/menu" "^0.44.0"
|
|
||||||
"@material/menu-surface" "^0.44.0"
|
|
||||||
"@material/notched-outline" "^0.44.0"
|
|
||||||
"@material/radio" "^0.44.0"
|
|
||||||
"@material/ripple" "^0.44.0"
|
|
||||||
"@material/rtl" "^0.42.0"
|
|
||||||
"@material/select" "^0.44.0"
|
|
||||||
"@material/selection-control" "^0.44.0"
|
|
||||||
"@material/shape" "^0.43.0"
|
|
||||||
"@material/slider" "^0.44.0"
|
|
||||||
"@material/snackbar" "^0.44.0"
|
|
||||||
"@material/switch" "^0.44.0"
|
|
||||||
"@material/tab" "^0.44.0"
|
|
||||||
"@material/tab-bar" "^0.44.0"
|
|
||||||
"@material/tab-indicator" "^0.43.0"
|
|
||||||
"@material/tab-scroller" "^0.44.0"
|
|
||||||
"@material/textfield" "^0.44.0"
|
|
||||||
"@material/theme" "^0.43.0"
|
|
||||||
"@material/toolbar" "^0.44.0"
|
|
||||||
"@material/top-app-bar" "^0.44.0"
|
|
||||||
"@material/typography" "^0.44.0"
|
|
||||||
|
|
||||||
object-assign@^4.1.1:
|
|
||||||
version "4.1.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
|
|
||||||
integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=
|
|
||||||
|
|
||||||
prop-types@^15.6.2:
|
|
||||||
version "15.7.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.1.tgz#2fa61e0a699d428b40320127733ee2931f05d9d1"
|
|
||||||
integrity sha512-f8Lku2z9kERjOCcnDOPm68EBJAO2K00Q5mSgPAUE/gJuBgsYLbVy6owSrtcHj90zt8PvW+z0qaIIgsIhHOa1Qw==
|
|
||||||
dependencies:
|
|
||||||
object-assign "^4.1.1"
|
|
||||||
react-is "^16.8.1"
|
|
||||||
|
|
||||||
react-dom@^16.8.1:
|
|
||||||
version "16.8.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.8.1.tgz#ec860f98853d09d39bafd3a6f1e12389d283dbb4"
|
|
||||||
integrity sha512-N74IZUrPt6UiDjXaO7UbDDFXeUXnVhZzeRLy/6iqqN1ipfjrhR60Bp5NuBK+rv3GMdqdIuwIl22u1SYwf330bg==
|
|
||||||
dependencies:
|
|
||||||
loose-envify "^1.1.0"
|
|
||||||
object-assign "^4.1.1"
|
|
||||||
prop-types "^15.6.2"
|
|
||||||
scheduler "^0.13.1"
|
|
||||||
|
|
||||||
react-is@^16.8.1:
|
|
||||||
version "16.8.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.8.1.tgz#a80141e246eb894824fb4f2901c0c50ef31d4cdb"
|
|
||||||
integrity sha512-ioMCzVDWvCvKD8eeT+iukyWrBGrA3DiFYkXfBsVYIRdaREZuBjENG+KjrikavCLasozqRWTwFUagU/O4vPpRMA==
|
|
||||||
|
|
||||||
react@^16.8.1:
|
|
||||||
version "16.8.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/react/-/react-16.8.1.tgz#ae11831f6cb2a05d58603a976afc8a558e852c4a"
|
|
||||||
integrity sha512-wLw5CFGPdo7p/AgteFz7GblI2JPOos0+biSoxf1FPsGxWQZdN/pj6oToJs1crn61DL3Ln7mN86uZ4j74p31ELQ==
|
|
||||||
dependencies:
|
|
||||||
loose-envify "^1.1.0"
|
|
||||||
object-assign "^4.1.1"
|
|
||||||
prop-types "^15.6.2"
|
|
||||||
scheduler "^0.13.1"
|
|
||||||
|
|
||||||
scheduler@^0.13.1:
|
|
||||||
version "0.13.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.13.1.tgz#1a217df1bfaabaf4f1b92a9127d5d732d85a9591"
|
|
||||||
integrity sha512-VJKOkiKIN2/6NOoexuypwSrybx13MY7NSy9RNt8wPvZDMRT1CW6qlpF5jXRToXNHz3uWzbm2elNpZfXfGPqP9A==
|
|
||||||
dependencies:
|
|
||||||
loose-envify "^1.1.0"
|
|
||||||
object-assign "^4.1.1"
|
|
||||||
|
|
||||||
tabbable@^3.1.2:
|
|
||||||
version "3.1.2"
|
|
||||||
resolved "https://registry.yarnpkg.com/tabbable/-/tabbable-3.1.2.tgz#f2d16cccd01f400e38635c7181adfe0ad965a4a2"
|
|
||||||
integrity sha512-wjB6puVXTYO0BSFtCmWQubA/KIn7Xvajw0x0l6eJUudMG/EAiJvIUnyNX6xO4NpGrJ16lbD0eUseB9WxW0vlpQ==
|
|
||||||
|
|
||||||
xtend@^4.0.1:
|
|
||||||
version "4.0.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af"
|
|
||||||
integrity sha1-pcbVMr5lbiPbgg77lDofBJmNY68=
|
|
|
@ -1,4 +0,0 @@
|
||||||
{
|
|
||||||
"name": "@coder/disposable",
|
|
||||||
"main": "src/index.ts"
|
|
||||||
}
|
|
|
@ -1,3 +0,0 @@
|
||||||
export interface IDisposable {
|
|
||||||
dispose(): void;
|
|
||||||
}
|
|
|
@ -1 +0,0 @@
|
||||||
export * from "./disposable";
|
|
|
@ -1,4 +0,0 @@
|
||||||
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
|
|
||||||
# yarn lockfile v1
|
|
||||||
|
|
||||||
|
|
|
@ -1,18 +0,0 @@
|
||||||
# This file specifies files that are *not* uploaded to Google Cloud Platform
|
|
||||||
# using gcloud. It follows the same syntax as .gitignore, with the addition of
|
|
||||||
# "#!include" directives (which insert the entries of the given .gitignore-style
|
|
||||||
# file at that point).
|
|
||||||
#
|
|
||||||
# For more information, run:
|
|
||||||
# $ gcloud topic gcloudignore
|
|
||||||
#
|
|
||||||
.gcloudignore
|
|
||||||
# If you would like to upload your .git directory, .gitignore file or files
|
|
||||||
# from your .gitignore file, remove the corresponding line
|
|
||||||
# below:
|
|
||||||
.git
|
|
||||||
.gitignore
|
|
||||||
src
|
|
||||||
|
|
||||||
# Node.js dependencies:
|
|
||||||
node_modules/
|
|
|
@ -1,8 +0,0 @@
|
||||||
FROM node
|
|
||||||
|
|
||||||
COPY out/main.js /main.js
|
|
||||||
COPY package.json /package.json
|
|
||||||
RUN yarn
|
|
||||||
ENV NODE_ENV production
|
|
||||||
|
|
||||||
CMD ["node", "/main.js"]
|
|
|
@ -1,5 +0,0 @@
|
||||||
runtime: nodejs10
|
|
||||||
service: cdrdns
|
|
||||||
network:
|
|
||||||
forwarded_ports:
|
|
||||||
- 53/udp
|
|
|
@ -1,14 +0,0 @@
|
||||||
{
|
|
||||||
"name": "@coder/dns",
|
|
||||||
"main": "out/main.js",
|
|
||||||
"scripts": {
|
|
||||||
"build": "../../node_modules/.bin/webpack --config ./webpack.config.js"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"node-named": "^0.0.1"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"ip-address": "^5.8.9",
|
|
||||||
"@types/ip-address": "^5.8.2"
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,109 +0,0 @@
|
||||||
import { field, logger } from "@coder/logger";
|
|
||||||
import * as http from "http";
|
|
||||||
//@ts-ignore
|
|
||||||
import * as named from "node-named";
|
|
||||||
import * as ip from "ip-address";
|
|
||||||
import { words, wordKeys } from "./words";
|
|
||||||
|
|
||||||
import * as dgram from "dgram";
|
|
||||||
|
|
||||||
const oldCreate = dgram.createSocket;
|
|
||||||
|
|
||||||
// tslint:disable-next-line:no-any
|
|
||||||
(<any>dgram).createSocket = (_: any, callback: any): dgram.Socket => {
|
|
||||||
return oldCreate("udp4", callback);
|
|
||||||
};
|
|
||||||
|
|
||||||
interface DnsQuery {
|
|
||||||
name(): string;
|
|
||||||
// tslint:disable-next-line:no-any
|
|
||||||
addAnswer(domain: string, target: any, ttl: number): void;
|
|
||||||
}
|
|
||||||
|
|
||||||
const dnsServer: {
|
|
||||||
listen(port: number, host: string, callback: () => void): void;
|
|
||||||
on(event: "query", callback: (query: DnsQuery) => void): void;
|
|
||||||
send(query: DnsQuery): void;
|
|
||||||
} = named.createServer();
|
|
||||||
|
|
||||||
const isDev = process.env.NODE_ENV !== "production";
|
|
||||||
const dnsPort = isDev ? 9999 : 53;
|
|
||||||
dnsServer.listen(dnsPort, "0.0.0.0", () => {
|
|
||||||
logger.info("DNS server started", field("port", dnsPort));
|
|
||||||
});
|
|
||||||
|
|
||||||
dnsServer.on("query", (query) => {
|
|
||||||
const domain = query.name();
|
|
||||||
const reqParts = domain.split(".");
|
|
||||||
if (reqParts.length < 2) {
|
|
||||||
dnsServer.send(query);
|
|
||||||
logger.info("Invalid request", field("request", domain));
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const allWords = reqParts.shift()!;
|
|
||||||
if (allWords.length > 16) {
|
|
||||||
dnsServer.send(query);
|
|
||||||
logger.info("Invalid request", field("request", domain));
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const wordParts = allWords.split(/(?=[A-Z])/);
|
|
||||||
const ipParts: string[] = [];
|
|
||||||
// Should be left with HowAreYouNow
|
|
||||||
for (let i = 0; i < wordParts.length; i++) {
|
|
||||||
const part = wordParts[i];
|
|
||||||
if (part.length > 4) {
|
|
||||||
dnsServer.send(query);
|
|
||||||
logger.info("Words too long", field("request", domain));
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const ipPart = words[part.toLowerCase()];
|
|
||||||
if (typeof ipPart === "undefined") {
|
|
||||||
dnsServer.send(query);
|
|
||||||
logger.info("Word not found in index", field("part", part), field("request", domain));
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ipParts.push(ipPart.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
const address = new ip.Address4(ipParts.join("."));
|
|
||||||
|
|
||||||
if (address.isValid()) {
|
|
||||||
logger.info("Responded with valid address query", field("address", address.address), field("request", domain));
|
|
||||||
query.addAnswer(domain, new named.ARecord(address.address), 99999);
|
|
||||||
} else {
|
|
||||||
logger.warn("Received invalid request", field("request", domain));
|
|
||||||
}
|
|
||||||
|
|
||||||
dnsServer.send(query);
|
|
||||||
});
|
|
||||||
|
|
||||||
const httpServer = http.createServer((request, response) => {
|
|
||||||
const remoteAddr = request.connection.remoteAddress;
|
|
||||||
if (!remoteAddr) {
|
|
||||||
response.writeHead(422);
|
|
||||||
response.end();
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const hostHeader = request.headers.host;
|
|
||||||
if (!hostHeader) {
|
|
||||||
response.writeHead(422);
|
|
||||||
response.end();
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const host = remoteAddr.split(".").map(p => wordKeys[Number.parseInt(p, 10)]).map(s => s.charAt(0).toUpperCase() + s.slice(1)).join("");
|
|
||||||
logger.info("Resolved host", field("remote-addr", remoteAddr), field("host", host));
|
|
||||||
response.writeHead(200);
|
|
||||||
response.write(`${host}.${hostHeader}`);
|
|
||||||
response.end();
|
|
||||||
});
|
|
||||||
|
|
||||||
const httpPort = isDev ? 3000 : 80;
|
|
||||||
httpServer.listen(httpPort, "0.0.0.0", () => {
|
|
||||||
logger.info("HTTP server started", field("port", httpPort));
|
|
||||||
});
|
|
|
@ -1,260 +0,0 @@
|
||||||
export const words: { readonly [key: string]: number } = {
|
|
||||||
term: 0,
|
|
||||||
salt: 1,
|
|
||||||
barn: 2,
|
|
||||||
corn: 3,
|
|
||||||
went: 4,
|
|
||||||
feel: 5,
|
|
||||||
rest: 6,
|
|
||||||
will: 7,
|
|
||||||
pale: 8,
|
|
||||||
cave: 9,
|
|
||||||
dirt: 10,
|
|
||||||
time: 11,
|
|
||||||
in: 12,
|
|
||||||
pie: 13,
|
|
||||||
star: 14,
|
|
||||||
iron: 15,
|
|
||||||
door: 16,
|
|
||||||
tone: 17,
|
|
||||||
want: 18,
|
|
||||||
task: 19,
|
|
||||||
zoo: 20,
|
|
||||||
nor: 21,
|
|
||||||
fall: 22,
|
|
||||||
tell: 23,
|
|
||||||
noon: 24,
|
|
||||||
new: 25,
|
|
||||||
per: 26,
|
|
||||||
end: 27,
|
|
||||||
arm: 28,
|
|
||||||
been: 29,
|
|
||||||
wolf: 30,
|
|
||||||
port: 31,
|
|
||||||
beat: 32,
|
|
||||||
pour: 33,
|
|
||||||
far: 34,
|
|
||||||
may: 35,
|
|
||||||
tie: 36,
|
|
||||||
moon: 37,
|
|
||||||
duck: 38,
|
|
||||||
us: 39,
|
|
||||||
led: 40,
|
|
||||||
met: 41,
|
|
||||||
bank: 42,
|
|
||||||
day: 43,
|
|
||||||
due: 44,
|
|
||||||
both: 45,
|
|
||||||
pet: 46,
|
|
||||||
gate: 47,
|
|
||||||
pain: 48,
|
|
||||||
rock: 49,
|
|
||||||
fill: 50,
|
|
||||||
open: 51,
|
|
||||||
thus: 52,
|
|
||||||
mark: 53,
|
|
||||||
our: 54,
|
|
||||||
loud: 55,
|
|
||||||
wife: 56,
|
|
||||||
say: 57,
|
|
||||||
flag: 58,
|
|
||||||
as: 59,
|
|
||||||
ride: 60,
|
|
||||||
once: 61,
|
|
||||||
sun: 62,
|
|
||||||
duty: 63,
|
|
||||||
pure: 64,
|
|
||||||
made: 65,
|
|
||||||
gulf: 66,
|
|
||||||
pig: 67,
|
|
||||||
fish: 68,
|
|
||||||
name: 69,
|
|
||||||
army: 70,
|
|
||||||
have: 71,
|
|
||||||
ill: 72,
|
|
||||||
meal: 73,
|
|
||||||
ago: 74,
|
|
||||||
late: 75,
|
|
||||||
view: 76,
|
|
||||||
atom: 77,
|
|
||||||
pen: 78,
|
|
||||||
mud: 79,
|
|
||||||
tail: 80,
|
|
||||||
sink: 81,
|
|
||||||
cow: 82,
|
|
||||||
rear: 83,
|
|
||||||
fur: 84,
|
|
||||||
go: 85,
|
|
||||||
suit: 86,
|
|
||||||
come: 87,
|
|
||||||
fear: 88,
|
|
||||||
also: 89,
|
|
||||||
sail: 90,
|
|
||||||
row: 91,
|
|
||||||
lay: 92,
|
|
||||||
noun: 93,
|
|
||||||
hat: 94,
|
|
||||||
am: 95,
|
|
||||||
mail: 96,
|
|
||||||
keep: 97,
|
|
||||||
drop: 98,
|
|
||||||
than: 99,
|
|
||||||
weak: 100,
|
|
||||||
by: 101,
|
|
||||||
who: 102,
|
|
||||||
fire: 103,
|
|
||||||
good: 104,
|
|
||||||
sick: 105,
|
|
||||||
care: 106,
|
|
||||||
pink: 107,
|
|
||||||
lady: 108,
|
|
||||||
war: 109,
|
|
||||||
sets: 110,
|
|
||||||
swam: 111,
|
|
||||||
well: 112,
|
|
||||||
shoe: 113,
|
|
||||||
bent: 114,
|
|
||||||
fuel: 115,
|
|
||||||
wet: 116,
|
|
||||||
fog: 117,
|
|
||||||
land: 118,
|
|
||||||
lead: 119,
|
|
||||||
tax: 120,
|
|
||||||
deal: 121,
|
|
||||||
verb: 122,
|
|
||||||
take: 123,
|
|
||||||
save: 124,
|
|
||||||
gift: 125,
|
|
||||||
had: 126,
|
|
||||||
gold: 127,
|
|
||||||
slow: 128,
|
|
||||||
drew: 129,
|
|
||||||
lamp: 130,
|
|
||||||
roof: 131,
|
|
||||||
hung: 132,
|
|
||||||
wild: 133,
|
|
||||||
able: 134,
|
|
||||||
girl: 135,
|
|
||||||
warn: 136,
|
|
||||||
were: 137,
|
|
||||||
know: 138,
|
|
||||||
camp: 139,
|
|
||||||
milk: 140,
|
|
||||||
neck: 141,
|
|
||||||
aid: 142,
|
|
||||||
fair: 143,
|
|
||||||
bell: 144,
|
|
||||||
dig: 145,
|
|
||||||
hope: 146,
|
|
||||||
wood: 147,
|
|
||||||
away: 148,
|
|
||||||
cook: 149,
|
|
||||||
just: 150,
|
|
||||||
form: 151,
|
|
||||||
food: 152,
|
|
||||||
hall: 153,
|
|
||||||
mind: 154,
|
|
||||||
for: 155,
|
|
||||||
card: 156,
|
|
||||||
half: 157,
|
|
||||||
sat: 158,
|
|
||||||
now: 159,
|
|
||||||
team: 160,
|
|
||||||
rush: 161,
|
|
||||||
face: 162,
|
|
||||||
wire: 163,
|
|
||||||
such: 164,
|
|
||||||
tool: 165,
|
|
||||||
make: 166,
|
|
||||||
fat: 167,
|
|
||||||
hold: 168,
|
|
||||||
inch: 169,
|
|
||||||
bill: 170,
|
|
||||||
mean: 171,
|
|
||||||
tide: 172,
|
|
||||||
burn: 173,
|
|
||||||
talk: 174,
|
|
||||||
tape: 175,
|
|
||||||
hard: 176,
|
|
||||||
mine: 177,
|
|
||||||
on: 178,
|
|
||||||
year: 179,
|
|
||||||
rich: 180,
|
|
||||||
sum: 181,
|
|
||||||
yes: 182,
|
|
||||||
baby: 183,
|
|
||||||
wide: 184,
|
|
||||||
how: 185,
|
|
||||||
clay: 186,
|
|
||||||
car: 187,
|
|
||||||
here: 188,
|
|
||||||
cent: 189,
|
|
||||||
bowl: 190,
|
|
||||||
post: 191,
|
|
||||||
said: 192,
|
|
||||||
see: 193,
|
|
||||||
raw: 194,
|
|
||||||
foot: 195,
|
|
||||||
life: 196,
|
|
||||||
bar: 197,
|
|
||||||
from: 198,
|
|
||||||
path: 199,
|
|
||||||
meat: 200,
|
|
||||||
show: 201,
|
|
||||||
sent: 202,
|
|
||||||
wait: 203,
|
|
||||||
mice: 204,
|
|
||||||
ten: 205,
|
|
||||||
pot: 206,
|
|
||||||
nice: 207,
|
|
||||||
idea: 208,
|
|
||||||
or: 209,
|
|
||||||
onto: 210,
|
|
||||||
rose: 211,
|
|
||||||
your: 212,
|
|
||||||
this: 213,
|
|
||||||
cat: 214,
|
|
||||||
bet: 215,
|
|
||||||
took: 216,
|
|
||||||
hang: 217,
|
|
||||||
very: 218,
|
|
||||||
bend: 219,
|
|
||||||
mix: 220,
|
|
||||||
base: 221,
|
|
||||||
jack: 222,
|
|
||||||
her: 223,
|
|
||||||
leg: 224,
|
|
||||||
own: 225,
|
|
||||||
book: 226,
|
|
||||||
love: 227,
|
|
||||||
dawn: 228,
|
|
||||||
deer: 229,
|
|
||||||
hit: 230,
|
|
||||||
rain: 231,
|
|
||||||
gas: 232,
|
|
||||||
eat: 233,
|
|
||||||
tube: 234,
|
|
||||||
case: 235,
|
|
||||||
pipe: 236,
|
|
||||||
get: 237,
|
|
||||||
joy: 238,
|
|
||||||
ever: 239,
|
|
||||||
nest: 240,
|
|
||||||
home: 241,
|
|
||||||
egg: 242,
|
|
||||||
pack: 243,
|
|
||||||
hand: 244,
|
|
||||||
cold: 245,
|
|
||||||
hot: 246,
|
|
||||||
frog: 247,
|
|
||||||
peep: 248,
|
|
||||||
seed: 249,
|
|
||||||
rawr: 250,
|
|
||||||
top: 251,
|
|
||||||
meow: 252,
|
|
||||||
bark: 253,
|
|
||||||
eel: 254,
|
|
||||||
swap: 255,
|
|
||||||
};
|
|
||||||
|
|
||||||
export const wordKeys = Object.keys(words);
|
|
|
@ -1,18 +0,0 @@
|
||||||
const path = require("path");
|
|
||||||
const merge = require("webpack-merge");
|
|
||||||
|
|
||||||
const root = path.resolve(__dirname, "../..");
|
|
||||||
|
|
||||||
module.exports = merge(
|
|
||||||
require(path.join(root, "scripts/webpack.node.config.js"))({
|
|
||||||
dirname: __dirname,
|
|
||||||
name: "dns",
|
|
||||||
}), {
|
|
||||||
externals: {
|
|
||||||
"node-named": "commonjs node-named",
|
|
||||||
},
|
|
||||||
entry: [
|
|
||||||
"./packages/dns/src/dns.ts"
|
|
||||||
],
|
|
||||||
},
|
|
||||||
);
|
|
|
@ -1,88 +0,0 @@
|
||||||
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
|
|
||||||
# yarn lockfile v1
|
|
||||||
|
|
||||||
|
|
||||||
"@types/ip-address@^5.8.2":
|
|
||||||
version "5.8.2"
|
|
||||||
resolved "https://registry.yarnpkg.com/@types/ip-address/-/ip-address-5.8.2.tgz#5e413c477f78b3a264745eac937538a6e6e0c1f6"
|
|
||||||
integrity sha512-LFlDGRjJDnahfPyNCZGXvlaevSmZTi/zDxjTdXeTs8TQ9pQkNZKbCWaJXW29a3bGPRsASqeO+jGgZlaTUi9jTw==
|
|
||||||
dependencies:
|
|
||||||
"@types/jsbn" "*"
|
|
||||||
|
|
||||||
"@types/jsbn@*":
|
|
||||||
version "1.2.29"
|
|
||||||
resolved "https://registry.yarnpkg.com/@types/jsbn/-/jsbn-1.2.29.tgz#28229bc0262c704a1506c3ed69a7d7e115bd7832"
|
|
||||||
integrity sha512-2dVz9LTEGWVj9Ov9zaDnpvqHFV+W4bXtU0EUEGAzWfdRNO3dlUuosdHpENI6/oQW+Kejn0hAjk6P/czs9h/hvg==
|
|
||||||
|
|
||||||
bunyan@0.7.0:
|
|
||||||
version "0.7.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/bunyan/-/bunyan-0.7.0.tgz#921065e70c936fe302a740e2c5605775beea2f42"
|
|
||||||
integrity sha1-khBl5wyTb+MCp0DixWBXdb7qL0I=
|
|
||||||
|
|
||||||
"coffee-script@>= 1.1.1":
|
|
||||||
version "1.12.7"
|
|
||||||
resolved "https://registry.yarnpkg.com/coffee-script/-/coffee-script-1.12.7.tgz#c05dae0cb79591d05b3070a8433a98c9a89ccc53"
|
|
||||||
integrity sha512-fLeEhqwymYat/MpTPUjSKHVYYl0ec2mOyALEMLmzr5i1isuG+6jfI2j2d5oBO3VIzgUXgBVIcOT9uH1TFxBckw==
|
|
||||||
|
|
||||||
ip-address@^5.8.9:
|
|
||||||
version "5.8.9"
|
|
||||||
resolved "https://registry.yarnpkg.com/ip-address/-/ip-address-5.8.9.tgz#6379277c23fc5adb20511e4d23ec2c1bde105dfd"
|
|
||||||
integrity sha512-7ay355oMN34iXhET1BmCJVsHjOTSItEEIIpOs38qUC23AIhOy+xIPnkrTuEFjeLMrTJ7m8KMXWgWfy/2Vn9sDw==
|
|
||||||
dependencies:
|
|
||||||
jsbn "1.1.0"
|
|
||||||
lodash.find "^4.6.0"
|
|
||||||
lodash.max "^4.0.1"
|
|
||||||
lodash.merge "^4.6.0"
|
|
||||||
lodash.padstart "^4.6.1"
|
|
||||||
lodash.repeat "^4.1.0"
|
|
||||||
sprintf-js "1.1.0"
|
|
||||||
|
|
||||||
ipaddr.js@0.1.1:
|
|
||||||
version "0.1.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-0.1.1.tgz#28c6a7c116a021c555544f906ab1ad540b1d635a"
|
|
||||||
integrity sha1-KManwRagIcVVVE+QarGtVAsdY1o=
|
|
||||||
dependencies:
|
|
||||||
coffee-script ">= 1.1.1"
|
|
||||||
|
|
||||||
jsbn@1.1.0:
|
|
||||||
version "1.1.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-1.1.0.tgz#b01307cb29b618a1ed26ec79e911f803c4da0040"
|
|
||||||
integrity sha1-sBMHyym2GKHtJux56RH4A8TaAEA=
|
|
||||||
|
|
||||||
lodash.find@^4.6.0:
|
|
||||||
version "4.6.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/lodash.find/-/lodash.find-4.6.0.tgz#cb0704d47ab71789ffa0de8b97dd926fb88b13b1"
|
|
||||||
integrity sha1-ywcE1Hq3F4n/oN6Ll92Sb7iLE7E=
|
|
||||||
|
|
||||||
lodash.max@^4.0.1:
|
|
||||||
version "4.0.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/lodash.max/-/lodash.max-4.0.1.tgz#8735566c618b35a9f760520b487ae79658af136a"
|
|
||||||
integrity sha1-hzVWbGGLNan3YFILSHrnllivE2o=
|
|
||||||
|
|
||||||
lodash.merge@^4.6.0:
|
|
||||||
version "4.6.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.1.tgz#adc25d9cb99b9391c59624f379fbba60d7111d54"
|
|
||||||
integrity sha512-AOYza4+Hf5z1/0Hztxpm2/xiPZgi/cjMqdnKTUWTBSKchJlxXXuUSxCCl8rJlf4g6yww/j6mA8nC8Hw/EZWxKQ==
|
|
||||||
|
|
||||||
lodash.padstart@^4.6.1:
|
|
||||||
version "4.6.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/lodash.padstart/-/lodash.padstart-4.6.1.tgz#d2e3eebff0d9d39ad50f5cbd1b52a7bce6bb611b"
|
|
||||||
integrity sha1-0uPuv/DZ05rVD1y9G1KnvOa7YRs=
|
|
||||||
|
|
||||||
lodash.repeat@^4.1.0:
|
|
||||||
version "4.1.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/lodash.repeat/-/lodash.repeat-4.1.0.tgz#fc7de8131d8c8ac07e4b49f74ffe829d1f2bec44"
|
|
||||||
integrity sha1-/H3oEx2MisB+S0n3T/6CnR8r7EQ=
|
|
||||||
|
|
||||||
node-named@^0.0.1:
|
|
||||||
version "0.0.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/node-named/-/node-named-0.0.1.tgz#3607b434cf237ab99440f5ff6d19c05e3a93e217"
|
|
||||||
integrity sha1-Nge0NM8jermUQPX/bRnAXjqT4hc=
|
|
||||||
dependencies:
|
|
||||||
bunyan "0.7.0"
|
|
||||||
ipaddr.js "0.1.1"
|
|
||||||
|
|
||||||
sprintf-js@1.1.0:
|
|
||||||
version "1.1.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.0.tgz#cffcaf702daf65ea39bb4e0fa2b299cec1a1be46"
|
|
||||||
integrity sha1-z/yvcC2vZeo5u04PorKZzsGhvkY=
|
|
|
@ -1,4 +0,0 @@
|
||||||
{
|
|
||||||
"name": "@coder/events",
|
|
||||||
"main": "./src/index.ts"
|
|
||||||
}
|
|
|
@ -1,99 +0,0 @@
|
||||||
import { IDisposable } from "@coder/disposable";
|
|
||||||
|
|
||||||
export interface Event<T> {
|
|
||||||
(listener: (value: T) => void): IDisposable;
|
|
||||||
(id: number | string, listener: (value: T) => void): IDisposable;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Emitter typecasts for a single event type. You can optionally use IDs, but
|
|
||||||
* using undefined with IDs will not work. If you emit without an ID, *all*
|
|
||||||
* listeners regardless of their ID (or lack thereof) will receive the event.
|
|
||||||
* Similarly, if you listen without an ID you will get *all* events for any or
|
|
||||||
* no ID.
|
|
||||||
*/
|
|
||||||
export class Emitter<T> {
|
|
||||||
private listeners = <Array<(value: T) => void>>[];
|
|
||||||
private readonly idListeners = new Map<number | string, Array<(value: T) => void>>();
|
|
||||||
|
|
||||||
public get event(): Event<T> {
|
|
||||||
return (id: number | string | ((value: T) => void), cb?: (value: T) => void): IDisposable => {
|
|
||||||
if (typeof id !== "function") {
|
|
||||||
if (this.idListeners.has(id)) {
|
|
||||||
this.idListeners.get(id)!.push(cb!);
|
|
||||||
} else {
|
|
||||||
this.idListeners.set(id, [cb!]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
dispose: (): void => {
|
|
||||||
if (this.idListeners.has(id)) {
|
|
||||||
const cbs = this.idListeners.get(id)!;
|
|
||||||
const i = cbs.indexOf(cb!);
|
|
||||||
if (i !== -1) {
|
|
||||||
cbs.splice(i, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
cb = id;
|
|
||||||
this.listeners.push(cb);
|
|
||||||
|
|
||||||
return {
|
|
||||||
dispose: (): void => {
|
|
||||||
const i = this.listeners.indexOf(cb!);
|
|
||||||
if (i !== -1) {
|
|
||||||
this.listeners.splice(i, 1);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Emit an event with a value.
|
|
||||||
*/
|
|
||||||
public emit(value: T): void;
|
|
||||||
public emit(id: number | string, value: T): void;
|
|
||||||
public emit(id: number | string | T, value?: T): void {
|
|
||||||
if ((typeof id === "number" || typeof id === "string") && typeof value !== "undefined") {
|
|
||||||
if (this.idListeners.has(id)) {
|
|
||||||
this.idListeners.get(id)!.forEach((cb) => cb(value!));
|
|
||||||
}
|
|
||||||
this.listeners.forEach((cb) => cb(value!));
|
|
||||||
} else {
|
|
||||||
this.idListeners.forEach((cbs) => cbs.forEach((cb) => cb((id as T)!)));
|
|
||||||
this.listeners.forEach((cb) => cb((id as T)!));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Dispose the current events.
|
|
||||||
*/
|
|
||||||
public dispose(): void;
|
|
||||||
public dispose(id: number | string): void;
|
|
||||||
public dispose(id?: number | string): void {
|
|
||||||
if (typeof id !== "undefined") {
|
|
||||||
this.idListeners.delete(id);
|
|
||||||
} else {
|
|
||||||
this.listeners = [];
|
|
||||||
this.idListeners.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public get counts(): { [key: string]: number } {
|
|
||||||
const counts = <{ [key: string]: number }>{};
|
|
||||||
if (this.listeners.length > 0) {
|
|
||||||
counts["n/a"] = this.listeners.length;
|
|
||||||
}
|
|
||||||
this.idListeners.forEach((cbs, id) => {
|
|
||||||
if (cbs.length > 0) {
|
|
||||||
counts[`${id}`] = cbs.length;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return counts;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1 +0,0 @@
|
||||||
export * from "./events";
|
|
|
@ -1,122 +0,0 @@
|
||||||
import { Emitter } from "../src/events";
|
|
||||||
|
|
||||||
describe("Event", () => {
|
|
||||||
const emitter = new Emitter<number>();
|
|
||||||
|
|
||||||
it("should listen to global event", () => {
|
|
||||||
const fn = jest.fn();
|
|
||||||
const d = emitter.event(fn);
|
|
||||||
emitter.emit(10);
|
|
||||||
expect(fn).toHaveBeenCalledWith(10);
|
|
||||||
d.dispose();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should listen to id event", () => {
|
|
||||||
const fn = jest.fn();
|
|
||||||
const d = emitter.event(0, fn);
|
|
||||||
emitter.emit(0, 5);
|
|
||||||
expect(fn).toHaveBeenCalledWith(5);
|
|
||||||
d.dispose();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should listen to string id event", () => {
|
|
||||||
const fn = jest.fn();
|
|
||||||
const d = emitter.event("string", fn);
|
|
||||||
emitter.emit("string", 55);
|
|
||||||
expect(fn).toHaveBeenCalledWith(55);
|
|
||||||
d.dispose();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should not listen wrong id event", () => {
|
|
||||||
const fn = jest.fn();
|
|
||||||
const d = emitter.event(1, fn);
|
|
||||||
emitter.emit(0, 5);
|
|
||||||
emitter.emit(1, 6);
|
|
||||||
expect(fn).toHaveBeenCalledWith(6);
|
|
||||||
expect(fn).toHaveBeenCalledTimes(1);
|
|
||||||
d.dispose();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should listen to id event globally", () => {
|
|
||||||
const fn = jest.fn();
|
|
||||||
const d = emitter.event(fn);
|
|
||||||
emitter.emit(1, 11);
|
|
||||||
expect(fn).toHaveBeenCalledWith(11);
|
|
||||||
d.dispose();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should listen to global event", () => {
|
|
||||||
const fn = jest.fn();
|
|
||||||
const d = emitter.event(3, fn);
|
|
||||||
emitter.emit(14);
|
|
||||||
expect(fn).toHaveBeenCalledWith(14);
|
|
||||||
d.dispose();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should listen to id event multiple times", () => {
|
|
||||||
const fn = jest.fn();
|
|
||||||
const disposers = [
|
|
||||||
emitter.event(934, fn),
|
|
||||||
emitter.event(934, fn),
|
|
||||||
emitter.event(934, fn),
|
|
||||||
emitter.event(934, fn),
|
|
||||||
];
|
|
||||||
emitter.emit(934, 324);
|
|
||||||
expect(fn).toHaveBeenCalledTimes(4);
|
|
||||||
expect(fn).toHaveBeenCalledWith(324);
|
|
||||||
disposers.forEach((d) => d.dispose());
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should dispose individually", () => {
|
|
||||||
const fn = jest.fn();
|
|
||||||
const d = emitter.event(fn);
|
|
||||||
|
|
||||||
const fn2 = jest.fn();
|
|
||||||
const d2 = emitter.event(1, fn2);
|
|
||||||
|
|
||||||
d.dispose();
|
|
||||||
|
|
||||||
emitter.emit(12);
|
|
||||||
emitter.emit(1, 12);
|
|
||||||
|
|
||||||
expect(fn).not.toBeCalled();
|
|
||||||
expect(fn2).toBeCalledTimes(2);
|
|
||||||
|
|
||||||
d2.dispose();
|
|
||||||
|
|
||||||
emitter.emit(12);
|
|
||||||
emitter.emit(1, 12);
|
|
||||||
|
|
||||||
expect(fn).not.toBeCalled();
|
|
||||||
expect(fn2).toBeCalledTimes(2);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should dispose by id", () => {
|
|
||||||
const fn = jest.fn();
|
|
||||||
emitter.event(fn);
|
|
||||||
|
|
||||||
const fn2 = jest.fn();
|
|
||||||
emitter.event(1, fn2);
|
|
||||||
|
|
||||||
emitter.dispose(1);
|
|
||||||
|
|
||||||
emitter.emit(12);
|
|
||||||
emitter.emit(1, 12);
|
|
||||||
|
|
||||||
expect(fn).toBeCalledTimes(2);
|
|
||||||
expect(fn2).not.toBeCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should dispose all", () => {
|
|
||||||
const fn = jest.fn();
|
|
||||||
emitter.event(fn);
|
|
||||||
emitter.event(1, fn);
|
|
||||||
|
|
||||||
emitter.dispose();
|
|
||||||
|
|
||||||
emitter.emit(12);
|
|
||||||
emitter.emit(1, 12);
|
|
||||||
|
|
||||||
expect(fn).not.toBeCalled();
|
|
||||||
});
|
|
||||||
});
|
|