Merge pull request #857 from cdr/web
[v2] Rewrite code-server to use new web stuff
@ -1,9 +1,10 @@
|
||||
Dockerfile
|
||||
# Docs
|
||||
doc/
|
||||
# GitHub stuff
|
||||
build
|
||||
deployment
|
||||
doc
|
||||
.github
|
||||
.gitignore
|
||||
.node-version
|
||||
.travis.yml
|
||||
LICENSE
|
||||
README.md
|
||||
|
7
.gitignore
vendored
@ -1,8 +1,3 @@
|
||||
/lib
|
||||
node_modules
|
||||
dist
|
||||
out
|
||||
.DS_Store
|
||||
build
|
||||
release
|
||||
.vscode
|
||||
.cache
|
||||
|
@ -1 +1 @@
|
||||
10.15.1
|
||||
10.16.0
|
||||
|
15
.travis.yml
@ -1,6 +1,6 @@
|
||||
language: node_js
|
||||
node_js:
|
||||
- 10.15.1
|
||||
- 10.16.0
|
||||
services:
|
||||
- docker
|
||||
matrix:
|
||||
@ -8,20 +8,19 @@ matrix:
|
||||
- os: linux
|
||||
dist: trusty
|
||||
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
|
||||
dist: trusty
|
||||
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
|
||||
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:
|
||||
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get install libxkbfile-dev
|
||||
libsecret-1-dev; fi
|
||||
- npm install -g yarn@1.12.3
|
||||
- if [[ "$TRAVIS_BRANCH" == "master" ]]; then export MINIFY="true"; fi
|
||||
- if [[ "$TRAVIS_BRANCH" == "master" ]]; then export PACKAGE="true"; fi
|
||||
script:
|
||||
- scripts/build.sh
|
||||
- scripts/ci.bash
|
||||
before_deploy:
|
||||
- echo "$VERSION" "$TRAVIS_COMMIT"
|
||||
- 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.
|
||||
RUN apt-get update && apt-get install -y \
|
||||
@ -11,9 +13,10 @@ RUN npm install -g yarn@1.13
|
||||
WORKDIR /src
|
||||
COPY . .
|
||||
|
||||
# In the future, we can use https://github.com/yarnpkg/rfcs/pull/53 to make yarn use the node_modules
|
||||
# directly which should be fast as it is slow because it populates its own cache every time.
|
||||
RUN yarn && NODE_ENV=production yarn task build:server:binary
|
||||
RUN yarn \
|
||||
&& MINIFY=true yarn build "${vscodeVersion}" "${codeServerVersion}" \
|
||||
&& 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.
|
||||
FROM ubuntu:18.04
|
||||
@ -30,7 +33,7 @@ RUN apt-get update && apt-get install -y \
|
||||
wget
|
||||
|
||||
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.
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
WORKDIR /home/coder/project
|
||||
|
||||
# This assures we have a volume mounted even if the user forgot to do bind mount.
|
||||
# So that they do not lose their data if they delete the container.
|
||||
# This ensures we have a volume mounted even if the user forgot to do bind
|
||||
# mount. So that they do not lose their data if they delete the container.
|
||||
VOLUME [ "/home/coder/project" ]
|
||||
|
||||
COPY --from=0 /src/packages/server/cli-linux-x64 /usr/local/bin/code-server
|
||||
EXPOSE 8443
|
||||
COPY --from=0 /src/build/code-server /usr/local/bin/code-server
|
||||
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!**
|
||||
[Get the preview here](https://github.com/cdr/code-server/releases).
|
||||
(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.
|
||||
`code-server` is [VS Code](https://github.com/Microsoft/vscode) running on a
|
||||
remote server, accessible through the browser.
|
||||
|
||||
Try it out:
|
||||
```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.
|
||||
- If you have a Windows or Mac workstation, more easily develop for Linux.
|
||||
- Take advantage of large cloud servers to speed up tests, compilations, downloads, and more.
|
||||
- Preserve battery life when you're on the go.
|
||||
- All intensive computation runs on your server.
|
||||
- You're no longer running excess instances of Chrome.
|
||||
- **Consistent environment:** Code on your Chromebook, tablet, and laptop with a
|
||||
consistent dev environment. develop more easily for Linux if you have a
|
||||
Windows or Mac, and pick up where you left off when switching workstations.
|
||||
- **Server-powered:** Take advantage of large cloud servers to speed up tests,
|
||||
compilations, downloads, and more. Preserve battery life when you're on the go
|
||||
since all intensive computation runs on your server.
|
||||
|
||||
![Screenshot](/doc/assets/ide.png)
|
||||
![Screenshot](/doc/assets/ide.gif)
|
||||
|
||||
## Getting Started
|
||||
|
||||
[![Create a Droplet](./doc/assets/do-new-droplet-btn.svg)](https://marketplace.digitalocean.com/apps/code-server?action=deploy)
|
||||
|
||||
### Run over SSH
|
||||
|
||||
Use [sshcode](https://github.com/codercom/sshcode) for a simple setup.
|
||||
|
||||
### 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
|
||||
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)
|
||||
2. Start the binary with the project directory as the first argument
|
||||
- For self-hosting and other information see [doc/quickstart.md](doc/quickstart.md).
|
||||
- For hosting on cloud platforms see [doc/deploy.md](doc/deploy.md).
|
||||
|
||||
```
|
||||
code-server <initial directory to open>
|
||||
```
|
||||
> You will be prompted to enter the password shown in the CLI
|
||||
`code-server` should now be running at https://localhost:8443.
|
||||
|
||||
> 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.
|
||||
|
||||
For detailed instructions and troubleshooting, see the [self-hosted quick start guide](doc/self-hosted/index.md).
|
||||
|
||||
Quickstart guides for [Google Cloud](doc/admin/install/google_cloud.md), [AWS](doc/admin/install/aws.md), and [DigitalOcean](doc/admin/install/digitalocean.md).
|
||||
|
||||
How to [secure your setup](/doc/security/ssl.md).
|
||||
|
||||
## Development
|
||||
|
||||
### Known Issues
|
||||
### Build
|
||||
- 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`
|
||||
will try to compile the build directory as well.
|
||||
- For now `@coder/nbin` is a global dependency.
|
||||
- Run `yarn build ${vscodeVersion} ${codeServerVersion}` in this directory (for
|
||||
example: `yarn build 1.36.0 development`).
|
||||
- If you target the same VS Code version our Travis builds do everything will
|
||||
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).
|
||||
- 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
|
||||
code into a single binary.
|
||||
|
||||
## Known Issues
|
||||
- Uploading .vsix files 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.
|
||||
![Screenshot](/doc/assets/release.gif)
|
||||
- Windows support.
|
||||
- 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.
|
||||
|
||||
### Extensions
|
||||
|
||||
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.
|
||||
## Extensions
|
||||
At the moment we can't use the official VS Code Marketplace. We've created a
|
||||
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
|
||||
|
||||
Use the `--disable-telemetry` flag or set `DISABLE_TELEMETRY=true` to disable tracking ENTIRELY.
|
||||
|
||||
We use data collected to improve code-server.
|
||||
Use the `--disable-telemetry` flag to completely disable telemetry. We use the
|
||||
data collected to improve code-server.
|
||||
|
||||
## 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
|
||||
|
||||
[MIT](LICENSE)
|
||||
|
||||
## Enterprise
|
||||
|
||||
Visit [our website](https://coder.com/) for more information about our enterprise offering.
|
||||
Visit [our enterprise page](https://coder.com/enterprise) for more information
|
||||
about our enterprise offering.
|
||||
|
||||
## Commercialization
|
||||
|
||||
If you would like to commercialize code-server, please contact contact@coder.com.
|
||||
If you would like to commercialize code-server, please contact
|
||||
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 |
BIN
doc/assets/ide.gif
Normal file
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 |
75
doc/cros-install.md
Normal file
@ -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.
|
73
doc/deploy.md
Normal file
@ -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.
|
15
doc/examples/fail2ban.conf
Normal file
@ -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
|
||||
spec:
|
||||
ports:
|
||||
- port: 8443
|
||||
- port: 8080
|
||||
name: https
|
||||
protocol: TCP
|
||||
selector:
|
||||
@ -62,7 +62,7 @@ spec:
|
||||
imagePullPolicy: Always
|
||||
name: code-servery
|
||||
ports:
|
||||
- containerPort: 8443
|
||||
- containerPort: 8080
|
||||
name: https
|
||||
volumeMounts:
|
||||
- name: code-server-storage
|
||||
@ -71,4 +71,3 @@ spec:
|
||||
- name: code-server-storage
|
||||
persistentVolumeClaim:
|
||||
claimName: code-store
|
||||
|
@ -10,7 +10,7 @@ metadata:
|
||||
namespace: code-server
|
||||
spec:
|
||||
ports:
|
||||
- port: 8443
|
||||
- port: 8080
|
||||
name: https
|
||||
protocol: TCP
|
||||
selector:
|
||||
@ -39,5 +39,5 @@ spec:
|
||||
imagePullPolicy: Always
|
||||
name: code-server
|
||||
ports:
|
||||
- containerPort: 8443
|
||||
- containerPort: 8080
|
||||
name: https
|
35
doc/fail2ban.md
Normal file
@ -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.
|
57
doc/quickstart.md
Normal file
@ -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
|
7
main.js
Normal file
@ -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",
|
||||
"description": "Run VS Code remotely.",
|
||||
"scripts": {
|
||||
"build:rules": "cd ./rules && tsc -p .",
|
||||
"packages:install": "cd ./packages && yarn",
|
||||
"postinstall": "npm-run-all --parallel packages:install build:rules",
|
||||
"start": "cd ./packages/server && yarn start",
|
||||
"task": "ts-node -r tsconfig-paths/register build/tasks.ts",
|
||||
"test": "cd ./packages && yarn test"
|
||||
"ensure-in-vscode": "bash ./scripts/tasks.bash ensure-in-vscode",
|
||||
"preinstall": "yarn ensure-in-vscode && cd ../../../ && yarn || true",
|
||||
"postinstall": "rm -rf node_modules/@types/node",
|
||||
"start": "yarn ensure-in-vscode && nodemon --watch ../../../out --verbose ../../../out/vs/server/main.js",
|
||||
"watch": "yarn ensure-in-vscode && cd ../../../ && yarn watch",
|
||||
"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": {
|
||||
"@types/fs-extra": "^5.0.4",
|
||||
"@types/node": "^10.12.18",
|
||||
"@types/tar": "^4.0.0",
|
||||
"@types/trash": "^4.3.1",
|
||||
"cache-loader": "^2.0.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"
|
||||
"@coder/nbin": "^1.2.0",
|
||||
"@types/pem": "^1.9.5",
|
||||
"@types/safe-compare": "^1.1.0",
|
||||
"@types/tar-stream": "^1.6.1",
|
||||
"nodemon": "^1.19.1"
|
||||
},
|
||||
"resolutions": {
|
||||
"bindings": "1.3.0"
|
||||
"@types/node": "^10.12.12",
|
||||
"safe-buffer": "^5.1.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"node-loader": "^0.6.0",
|
||||
"node-pty": "0.8.1",
|
||||
"spdlog": "0.8.1",
|
||||
"webpack-merge": "^4.2.1"
|
||||
"@coder/logger": "^1.1.8",
|
||||
"httpolyglot": "^0.1.2",
|
||||
"pem": "^1.14.2",
|
||||
"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();
|
||||
});
|
||||
});
|