Featureful (#31)
* Fix loading within the CLI * Remove app * Remove promise handle * Add initial travis file * Add libxkbfile dependency * Add libxkbfile-dev * Add build script * Fix malformed bash statement * Remove yarn from script * Improve build script * Extract upx before usage * Only run upx if on linux * Ensure resource directory exists * Pack runnable binary * Export binary with platform * Improve build process * Install upx before running install script * Update typescript version before running nexe * Add os.release() function for multi-platform support * Update travis.yml to improve deployment * Add on CI * Update to v1.31.0 * Add libsecret * Update build target * Skip cleanup * Fix built-in extensions * Add basics for apps * Create custom DNS server * Fix forking within CLI. Fixes TS language features * Fix filename resolve * Fix default extensions path * Add custom dialog * Store workspace path * Remove outfiles * Cleanup * Always authed outside of CLI * Use location.host for client * Remove useless app interface * Remove debug file for building wordlist * Use chromes tcp host * Update patch * Build browser app before packaging * Replace all css containing file:// URLs, fix webviews * Fix save * Fix mkdir
This commit is contained in:
parent
bdd24081ab
commit
85d2225e0c
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,3 +1,4 @@
|
||||
lib
|
||||
node_modules
|
||||
dist
|
||||
out
|
23
.travis.yml
Normal file
23
.travis.yml
Normal file
@ -0,0 +1,23 @@
|
||||
language: node_js
|
||||
node_js:
|
||||
- 8.9.3
|
||||
matrix:
|
||||
include:
|
||||
- os: linux
|
||||
dist: ubuntu
|
||||
- os: osx
|
||||
- os: windows
|
||||
before_install:
|
||||
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get install libxkbfile-dev libsecret-1-dev;
|
||||
fi
|
||||
script:
|
||||
- scripts/build.sh
|
||||
deploy:
|
||||
provider: releases
|
||||
skip_cleanup: true
|
||||
api_key:
|
||||
secure: T/yqCIeqLifteriv8D3CnehNFzSBP309GZqeUfyx8Q+xSQEttA9Enxl+Qw9GkdedYTN4J56iucHIac6CwcvKSKIXqk80CeSEW0BNxZs5wIgv4rRMMy/GAX0NBWKNOkoGlH8M6VyQcM7eY2iGAn1EX755PHalk6rWwfsauRANOQyb2DXQBan5C0YUnogq2qcW1xkIwlXH7l0Ekbtego0f6QPv0rSyOcL1LKm6xk0Aq+xLNKJkT6TSL6xYpkPlZLjnql09Nspkqs6NehWlft2n09bHqAtjNnWw9OYCvxp8mdHeTE5uShuEqYPzdYU5LVFoE7wElI8uqS66noaA18ytZYGw2IrY6GZcn+wtR6WyM2+YXl2HclL1/Fs6Vn8+zwq2IBZchBNv3KJSn1dxiqLlD/s6YQyni17x/9FhtFoNUvsbY5zSC1xrnNQBQWFg0TRnoC9rPR+7hQtT1+5+CvRxpvcNWnPuA22919PFE79ejJulPmsnyF+YLs9c6APJgOpOO1f6fKt5Mcb02dubPqGcQ9NbqUUNTl4IUvEtjG0LnFAgEGerxAcsdnUTxzBVf0LJLlhRKW1BigUTbRwfUJL1DN0mWg9cg7fL5VqrogvNq3uRguxOsYr+bcHDbimQSAY3No3fAkTTqQSJh56Dx57/Un18KxuOTiRB9de1RtiudsI=
|
||||
file: packages/server/cli-$TRAVIS_OS_NAME
|
||||
on:
|
||||
repo: codercom/vscode-online
|
||||
all_branches: true
|
195
build/tasks.ts
Normal file
195
build/tasks.ts
Normal file
@ -0,0 +1,195 @@
|
||||
import { register, run } from "@coder/runner";
|
||||
import * as fs from "fs";
|
||||
import * as fse from "fs-extra";
|
||||
import * as path from "path";
|
||||
import * as zlib from "zlib";
|
||||
|
||||
const libPath = path.join(__dirname, "../lib");
|
||||
const vscodePath = path.join(libPath, "vscode");
|
||||
const pkgsPath = path.join(__dirname, "../packages");
|
||||
const defaultExtensionsPath = path.join(libPath, "VSCode-linux-x64/resources/app/extensions");
|
||||
|
||||
const buildServerBinary = register("build:server:binary", async (runner) => {
|
||||
await ensureInstalled();
|
||||
await copyForDefaultExtensions();
|
||||
await Promise.all([
|
||||
buildBootstrapFork(),
|
||||
buildWeb(),
|
||||
buildDefaultExtensions(),
|
||||
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 web bundle built");
|
||||
}
|
||||
await buildServerBinaryCopy();
|
||||
const resp = await runner.execute("npm", ["run", "build:nexe"]);
|
||||
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", "bin", "bootstrap-fork.js");
|
||||
const webOutputPath = path.join(pkgsPath, "web", "out");
|
||||
const browserAppOutputPath = path.join(pkgsPath, "app", "browser", "out");
|
||||
const nodePtyModule = path.join(pkgsPath, "protocol", "node_modules", "node-pty", "build", "Release", "pty.node");
|
||||
|
||||
if (!fs.existsSync(nodePtyModule)) {
|
||||
throw new Error("Could not find pty.node. Ensure all packages have been installed");
|
||||
}
|
||||
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");
|
||||
}
|
||||
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, subdir: "auth" | "unauth", rootPath: string): void => {
|
||||
const stat = fs.statSync(dir);
|
||||
if (stat.isDirectory()) {
|
||||
const paths = fs.readdirSync(dir);
|
||||
paths.forEach((p) => cpDir(path.join(dir, p), subdir, rootPath));
|
||||
} 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, "auth", webOutputPath);
|
||||
cpDir(browserAppOutputPath, "unauth", browserAppOutputPath);
|
||||
fse.mkdirpSync(path.join(cliBuildPath, "modules"));
|
||||
fse.copySync(nodePtyModule, path.join(cliBuildPath, "modules", "pty.node"));
|
||||
});
|
||||
|
||||
const buildServerBundle = register("build:server:bundle", async (runner) => {
|
||||
const cliPath = path.join(pkgsPath, "server");
|
||||
runner.cwd = cliPath;
|
||||
await runner.execute("npm", ["run", "build:webpack"]);
|
||||
});
|
||||
|
||||
const buildBootstrapFork = register("build:bootstrap-fork", async (runner) => {
|
||||
await ensureInstalled();
|
||||
await ensurePatched();
|
||||
|
||||
const vscodePkgPath = path.join(pkgsPath, "vscode");
|
||||
runner.cwd = vscodePkgPath;
|
||||
await runner.execute("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("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("npm", ["run", "build"]);
|
||||
});
|
||||
|
||||
const extDirPath = path.join("lib", "vscode-default-extensions");
|
||||
const copyForDefaultExtensions = register("build:copy-vscode", async (runner) => {
|
||||
if (!fs.existsSync(defaultExtensionsPath)) {
|
||||
await ensureClean();
|
||||
fse.removeSync(extDirPath);
|
||||
fse.copySync(vscodePath, extDirPath);
|
||||
}
|
||||
});
|
||||
|
||||
const buildDefaultExtensions = register("build:default-extensions", async (runner) => {
|
||||
if (!fs.existsSync(defaultExtensionsPath)) {
|
||||
await copyForDefaultExtensions();
|
||||
runner.cwd = extDirPath;
|
||||
const resp = await runner.execute("npx", ["gulp", "vscode-linux-x64"]);
|
||||
if (resp.exitCode !== 0) {
|
||||
throw new Error(`Failed to build default extensions: ${resp.stderr}`);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const ensureInstalled = register("vscode:install", async (runner) => {
|
||||
await ensureCloned();
|
||||
|
||||
runner.cwd = vscodePath;
|
||||
const install = await runner.execute("yarn", []);
|
||||
if (install.exitCode !== 0) {
|
||||
throw new Error(`Failed to install vscode dependencies: ${install.stderr}`);
|
||||
}
|
||||
});
|
||||
|
||||
const ensureCloned = register("vscode:clone", async (runner) => {
|
||||
if (fs.existsSync(vscodePath)) {
|
||||
await ensureClean();
|
||||
} else {
|
||||
fs.mkdirSync(libPath);
|
||||
runner.cwd = libPath;
|
||||
const clone = await runner.execute("git", ["clone", "https://github.com/microsoft/vscode"]);
|
||||
if (clone.exitCode !== 0) {
|
||||
throw new Error(`Failed to clone: ${clone.exitCode}`);
|
||||
}
|
||||
}
|
||||
|
||||
runner.cwd = vscodePath;
|
||||
const checkout = await runner.execute("git", ["checkout", "tags/1.31.0"]);
|
||||
if (checkout.exitCode !== 0) {
|
||||
throw new Error(`Failed to checkout: ${checkout.stderr}`);
|
||||
}
|
||||
});
|
||||
|
||||
const ensureClean = register("vscode:clean", async (runner) => {
|
||||
runner.cwd = vscodePath;
|
||||
|
||||
const status = await runner.execute("git", ["status", "--porcelain"]);
|
||||
if (status.stdout.trim() !== "") {
|
||||
const clean = await runner.execute("git", ["clean", "-f", "-d", "-X"]);
|
||||
if (clean.exitCode !== 0) {
|
||||
throw new Error(`Failed to clean git repository: ${clean.stderr}`);
|
||||
}
|
||||
const removeUnstaged = await runner.execute("git", ["checkout", "--", "."]);
|
||||
if (removeUnstaged.exitCode !== 0) {
|
||||
throw new Error(`Failed to remove unstaged files: ${removeUnstaged.stderr}`);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const ensurePatched = register("vscode:patch", async (runner) => {
|
||||
if (!fs.existsSync(vscodePath)) {
|
||||
throw new Error("vscode must be cloned to patch");
|
||||
}
|
||||
await ensureClean();
|
||||
|
||||
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}`);
|
||||
}
|
||||
});
|
||||
|
||||
run();
|
@ -6,21 +6,21 @@
|
||||
"description": "Run VS Code remotely.",
|
||||
"scripts": {
|
||||
"build:rules": "cd ./rules && tsc -p .",
|
||||
"vscode:clone": "mkdir -p ./lib && test -d ./lib/vscode || git clone https://github.com/Microsoft/vscode/ ./lib/vscode",
|
||||
"vscode:install": "cd ./lib/vscode && git checkout tags/1.30.1 && yarn",
|
||||
"vscode": "npm-run-all vscode:*",
|
||||
"packages:install": "cd ./packages && yarn",
|
||||
"postinstall": "npm-run-all --parallel vscode packages:install build:rules",
|
||||
"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"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/fs-extra": "^5.0.4",
|
||||
"@types/node": "^10.12.18",
|
||||
"@types/trash": "^4.3.1",
|
||||
"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",
|
||||
@ -35,6 +35,7 @@
|
||||
"style-loader": "^0.23.1",
|
||||
"ts-loader": "^5.3.3",
|
||||
"ts-node": "^7.0.1",
|
||||
"tsconfig-paths": "^3.8.0",
|
||||
"tslint": "^5.12.1",
|
||||
"typescript": "^3.2.2",
|
||||
"typescript-tslint-plugin": "^0.2.1",
|
||||
|
10
packages/app/browser/package.json
Normal file
10
packages/app/browser/package.json
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"name": "@coder/app",
|
||||
"scripts": {
|
||||
"start": "../../../node_modules/.bin/webpack-dev-server --config ./webpack.config.js",
|
||||
"build": "../../../node_modules/.bin/webpack --config ./webpack.config.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"material-components-web": "^0.44.0"
|
||||
}
|
||||
}
|
43
packages/app/browser/src/app.html
Normal file
43
packages/app/browser/src/app.html
Normal file
@ -0,0 +1,43 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1">
|
||||
<title>Coder</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="login">
|
||||
<div class="back">
|
||||
<- Back </div> <h4 class="title">AWS Cloud</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>
|
||||
<div class="mdc-text-field-helper-line">
|
||||
<div class="mdc-text-field-helper-text">helper text</div>
|
||||
</div>
|
||||
<div class="mdc-form-field">
|
||||
<div class="mdc-checkbox">
|
||||
<input type="checkbox" class="mdc-checkbox__native-control" id="remember" />
|
||||
<div class="mdc-checkbox__background">
|
||||
<svg class="mdc-checkbox__checkmark" viewBox="0 0 24 24">
|
||||
<path class="mdc-checkbox__checkmark-path" fill="none" d="M1.73,12.91 8.1,19.28 22.79,4.59" />
|
||||
</svg>
|
||||
<div class="mdc-checkbox__mixedmark"></div>
|
||||
</div>
|
||||
</div>
|
||||
<label for="remember">Remember Me</label>
|
||||
</div>
|
||||
<button id="submit" class="mdc-button mdc-button--unelevated">
|
||||
<span class="mdc-button__label">Enter IDE</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
108
packages/app/browser/src/app.scss
Normal file
108
packages/app/browser/src/app.scss
Normal file
@ -0,0 +1,108 @@
|
||||
@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;
|
||||
}
|
30
packages/app/browser/src/app.ts
Normal file
30
packages/app/browser/src/app.ts
Normal file
@ -0,0 +1,30 @@
|
||||
//@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) => window["t"] = 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 submit = document.getElementById("submit") as HTMLButtonElement;
|
||||
if (!submit) {
|
||||
throw new Error("No submit button found");
|
||||
}
|
||||
submit.addEventListener("click", () => {
|
||||
document.cookie = `password=${password.value}`;
|
||||
location.reload();
|
||||
});
|
24
packages/app/browser/webpack.config.js
Normal file
24
packages/app/browser/webpack.config.js
Normal file
@ -0,0 +1,24 @@
|
||||
const path = require("path");
|
||||
const webpack = require("webpack");
|
||||
const merge = require("webpack-merge");
|
||||
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: prod ? "source-map" : "cheap-module-eval-source-map",
|
||||
mode: prod ? "production" : "development",
|
||||
output: {
|
||||
path: path.join(__dirname, "out"),
|
||||
},
|
||||
entry: [
|
||||
"webpack-hot-middleware/client?reload=true&quiet=true",
|
||||
"./packages/app/browser/src/app.ts"
|
||||
],
|
||||
plugins: [
|
||||
new HtmlWebpackPlugin({
|
||||
template: "packages/app/browser/src/app.html",
|
||||
}),
|
||||
new webpack.HotModuleReplacementPlugin(),
|
||||
// new BundleAnalyzerPlugin(),
|
||||
]
|
||||
});
|
518
packages/app/browser/yarn.lock
Normal file
518
packages/app/browser/yarn.lock
Normal file
@ -0,0 +1,518 @@
|
||||
# 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==
|
||||
|
||||
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=
|
BIN
packages/app/chrome/icon_128.png
Normal file
BIN
packages/app/chrome/icon_128.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 537 B |
42
packages/app/chrome/manifest.json
Normal file
42
packages/app/chrome/manifest.json
Normal file
@ -0,0 +1,42 @@
|
||||
{
|
||||
"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": [
|
||||
""
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
9
packages/app/chrome/package.json
Normal file
9
packages/app/chrome/package.json
Normal file
@ -0,0 +1,9 @@
|
||||
{
|
||||
"name": "@coder/chrome-app",
|
||||
"dependencies": {
|
||||
"@types/chrome": "^0.0.79"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "../../../node_modules/.bin/webpack --config ./webpack.config.js"
|
||||
}
|
||||
}
|
13
packages/app/chrome/src/background.ts
Normal file
13
packages/app/chrome/src/background.ts
Normal file
@ -0,0 +1,13 @@
|
||||
/// <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,
|
||||
},
|
||||
});
|
||||
});
|
92
packages/app/chrome/src/chome.ts
Normal file
92
packages/app/chrome/src/chome.ts
Normal file
@ -0,0 +1,92 @@
|
||||
//@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();
|
||||
});
|
||||
});
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
};
|
33
packages/app/chrome/src/content.ts
Normal file
33
packages/app/chrome/src/content.ts
Normal file
@ -0,0 +1,33 @@
|
||||
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,
|
||||
});
|
15
packages/app/chrome/src/index.html
Normal file
15
packages/app/chrome/src/index.html
Normal file
@ -0,0 +1,15 @@
|
||||
<!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>
|
37
packages/app/chrome/webpack.config.js
Normal file
37
packages/app/chrome/webpack.config.js
Normal file
@ -0,0 +1,37 @@
|
||||
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: [
|
||||
]
|
||||
}),
|
||||
];
|
22
packages/app/chrome/yarn.lock
Normal file
22
packages/app/chrome/yarn.lock
Normal file
@ -0,0 +1,22 @@
|
||||
# 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=
|
13
packages/app/common/package.json
Normal file
13
packages/app/common/package.json
Normal file
@ -0,0 +1,13 @@
|
||||
{
|
||||
"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"
|
||||
}
|
||||
}
|
279
packages/app/common/src/app.scss
Normal file
279
packages/app/common/src/app.scss
Normal file
@ -0,0 +1,279 @@
|
||||
@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;
|
||||
}
|
33
packages/app/common/src/app.tsx
Normal file
33
packages/app/common/src/app.tsx
Normal file
@ -0,0 +1,33 @@
|
||||
//@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);
|
||||
};
|
17
packages/app/common/src/connection.ts
Normal file
17
packages/app/common/src/connection.ts
Normal file
@ -0,0 +1,17 @@
|
||||
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>;
|
||||
}
|
573
packages/app/common/src/containers.tsx
Normal file
573
packages/app/common/src/containers.tsx
Normal file
@ -0,0 +1,573 @@
|
||||
//@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: "Kyle's Magic 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: "v1.31.0",
|
||||
});
|
||||
} 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"));
|
||||
// };
|
BIN
packages/app/common/src/fonts/AktivGroteskBold.eot
Normal file
BIN
packages/app/common/src/fonts/AktivGroteskBold.eot
Normal file
Binary file not shown.
BIN
packages/app/common/src/fonts/AktivGroteskBold.ttf
Normal file
BIN
packages/app/common/src/fonts/AktivGroteskBold.ttf
Normal file
Binary file not shown.
BIN
packages/app/common/src/fonts/AktivGroteskBold.woff
Normal file
BIN
packages/app/common/src/fonts/AktivGroteskBold.woff
Normal file
Binary file not shown.
BIN
packages/app/common/src/fonts/AktivGroteskBold.woff2
Normal file
BIN
packages/app/common/src/fonts/AktivGroteskBold.woff2
Normal file
Binary file not shown.
BIN
packages/app/common/src/fonts/AktivGroteskMedium.eot
Normal file
BIN
packages/app/common/src/fonts/AktivGroteskMedium.eot
Normal file
Binary file not shown.
BIN
packages/app/common/src/fonts/AktivGroteskMedium.ttf
Normal file
BIN
packages/app/common/src/fonts/AktivGroteskMedium.ttf
Normal file
Binary file not shown.
BIN
packages/app/common/src/fonts/AktivGroteskMedium.woff
Normal file
BIN
packages/app/common/src/fonts/AktivGroteskMedium.woff
Normal file
Binary file not shown.
BIN
packages/app/common/src/fonts/AktivGroteskMedium.woff2
Normal file
BIN
packages/app/common/src/fonts/AktivGroteskMedium.woff2
Normal file
Binary file not shown.
BIN
packages/app/common/src/fonts/AktivGroteskRegular.eot
Normal file
BIN
packages/app/common/src/fonts/AktivGroteskRegular.eot
Normal file
Binary file not shown.
BIN
packages/app/common/src/fonts/AktivGroteskRegular.ttf
Normal file
BIN
packages/app/common/src/fonts/AktivGroteskRegular.ttf
Normal file
Binary file not shown.
BIN
packages/app/common/src/fonts/AktivGroteskRegular.woff
Normal file
BIN
packages/app/common/src/fonts/AktivGroteskRegular.woff
Normal file
Binary file not shown.
BIN
packages/app/common/src/fonts/AktivGroteskRegular.woff2
Normal file
BIN
packages/app/common/src/fonts/AktivGroteskRegular.woff2
Normal file
Binary file not shown.
5
packages/app/common/src/storage.ts
Normal file
5
packages/app/common/src/storage.ts
Normal file
@ -0,0 +1,5 @@
|
||||
|
||||
export interface StorageProvider {
|
||||
set<T>(key: string, value: T): Promise<void>;
|
||||
get<T>(key: string): Promise<T | undefined>;
|
||||
}
|
24
packages/app/common/src/tooltip.scss
Normal file
24
packages/app/common/src/tooltip.scss
Normal file
@ -0,0 +1,24 @@
|
||||
.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);
|
||||
}
|
601
packages/app/common/yarn.lock
Normal file
601
packages/app/common/yarn.lock
Normal file
@ -0,0 +1,601 @@
|
||||
# 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=
|
18
packages/dns/.gcloudignore
Normal file
18
packages/dns/.gcloudignore
Normal file
@ -0,0 +1,18 @@
|
||||
# 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/
|
8
packages/dns/Dockerfile
Normal file
8
packages/dns/Dockerfile
Normal file
@ -0,0 +1,8 @@
|
||||
FROM node
|
||||
|
||||
COPY out/main.js /main.js
|
||||
COPY package.json /package.json
|
||||
RUN yarn
|
||||
ENV NODE_ENV production
|
||||
|
||||
CMD ["node", "/main.js"]
|
5
packages/dns/app.yaml
Normal file
5
packages/dns/app.yaml
Normal file
@ -0,0 +1,5 @@
|
||||
runtime: nodejs10
|
||||
service: cdrdns
|
||||
network:
|
||||
forwarded_ports:
|
||||
- 53/udp
|
14
packages/dns/package.json
Normal file
14
packages/dns/package.json
Normal file
@ -0,0 +1,14 @@
|
||||
{
|
||||
"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"
|
||||
}
|
||||
}
|
109
packages/dns/src/dns.ts
Normal file
109
packages/dns/src/dns.ts
Normal file
@ -0,0 +1,109 @@
|
||||
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));
|
||||
});
|
260
packages/dns/src/words.ts
Normal file
260
packages/dns/src/words.ts
Normal file
@ -0,0 +1,260 @@
|
||||
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);
|
18
packages/dns/webpack.config.js
Normal file
18
packages/dns/webpack.config.js
Normal file
@ -0,0 +1,18 @@
|
||||
const path = require("path");
|
||||
const merge = require("webpack-merge");
|
||||
|
||||
module.exports = merge(require(path.join(__dirname, "../../scripts", "webpack.general.config.js"))(), {
|
||||
devtool: "none",
|
||||
mode: "production",
|
||||
target: "node",
|
||||
externals: {
|
||||
"node-named": "commonjs node-named",
|
||||
},
|
||||
output: {
|
||||
path: path.join(__dirname, "out"),
|
||||
filename: "main.js",
|
||||
},
|
||||
entry: [
|
||||
"./packages/dns/src/dns.ts"
|
||||
],
|
||||
});
|
88
packages/dns/yarn.lock
Normal file
88
packages/dns/yarn.lock
Normal file
@ -0,0 +1,88 @@
|
||||
# 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=
|
@ -32,6 +32,13 @@ export abstract class IdeClient {
|
||||
logger.info("Loading IDE");
|
||||
this.loadTime = time(2500);
|
||||
|
||||
let appWindow: Window | undefined;
|
||||
window.addEventListener("message", (event) => {
|
||||
if (event.data === "app") {
|
||||
appWindow = event.source as Window;
|
||||
}
|
||||
});
|
||||
|
||||
this.sharedProcessData = new Promise((resolve): void => {
|
||||
client.onSharedProcessActive(resolve);
|
||||
});
|
||||
@ -48,6 +55,9 @@ export abstract class IdeClient {
|
||||
|
||||
this.initialize().then(() => {
|
||||
logger.info("Load completed", field("duration", this.loadTime));
|
||||
if (appWindow) {
|
||||
appWindow.postMessage("loaded", "*");
|
||||
}
|
||||
}).catch((error) => {
|
||||
logger.error(error.message);
|
||||
logger.warn("Load completed with errors", field("duration", this.loadTime));
|
||||
|
@ -92,7 +92,7 @@ class WebsocketConnection implements ReadWriteConnection {
|
||||
private async openSocket(): Promise<WebSocket> {
|
||||
this.dispose();
|
||||
const socket = new WebSocket(
|
||||
`${location.protocol === "https" ? "wss" : "ws"}://${location.host}`,
|
||||
`${location.protocol === "https:" ? "wss" : "ws"}://${location.host}`,
|
||||
);
|
||||
socket.binaryType = "arraybuffer";
|
||||
this.activeSocket = socket;
|
||||
|
@ -19,15 +19,59 @@ if (typeof document === "undefined") {
|
||||
(global as any).document = {} as any;
|
||||
}
|
||||
|
||||
const oldCreateElement: <K extends keyof HTMLElementTagNameMap>(
|
||||
tagName: K, options?: ElementCreationOptions,
|
||||
) => HTMLElementTagNameMap[K] = document.createElement;
|
||||
|
||||
const oldCreateElement = document.createElement;
|
||||
const newCreateElement = <K extends keyof HTMLElementTagNameMap>(tagName: K): HTMLElementTagNameMap[K] => {
|
||||
const createElement = <K extends keyof HTMLElementTagNameMap>(tagName: K): HTMLElementTagNameMap[K] => {
|
||||
return oldCreateElement.call(document, tagName);
|
||||
// tslint:disable-next-line:no-any
|
||||
return oldCreateElement.call(document, tagName as any);
|
||||
};
|
||||
|
||||
if (tagName === "style") {
|
||||
const style = createElement("style");
|
||||
// tslint:disable-next-line:no-any
|
||||
const getPropertyDescriptor = (object: any, id: string): PropertyDescriptor | undefined => {
|
||||
let op = Object.getPrototypeOf(object);
|
||||
while (!Object.getOwnPropertyDescriptor(op, id)) {
|
||||
op = Object.getPrototypeOf(op);
|
||||
}
|
||||
|
||||
return Object.getOwnPropertyDescriptor(op, id);
|
||||
};
|
||||
const oldInnerHtml = getPropertyDescriptor(style, "innerHTML");
|
||||
if (!oldInnerHtml) {
|
||||
throw new Error("Failed to find innerHTML property");
|
||||
}
|
||||
Object.defineProperty(style, "innerHTML", {
|
||||
get: (): string => {
|
||||
return oldInnerHtml!.get!.call(style);
|
||||
},
|
||||
set: (value: string): void => {
|
||||
value = value.replace(/file:\/\//g, "/resource");
|
||||
oldInnerHtml!.set!.call(style, value);
|
||||
},
|
||||
});
|
||||
let overridden = false;
|
||||
const oldSheet = getPropertyDescriptor(style, "sheet");
|
||||
Object.defineProperty(style, "sheet", {
|
||||
// tslint:disable-next-line:no-any
|
||||
get: (): any => {
|
||||
const sheet = oldSheet!.get!.call(style);
|
||||
if (sheet && !overridden) {
|
||||
const oldInsertRule = sheet.insertRule;
|
||||
sheet.insertRule = (rule: string, index?: number): void => {
|
||||
rule = rule.replace(/file:\/\//g, "/resource");
|
||||
oldInsertRule.call(sheet, rule, index);
|
||||
};
|
||||
overridden = true;
|
||||
}
|
||||
|
||||
return sheet;
|
||||
},
|
||||
});
|
||||
|
||||
return style;
|
||||
}
|
||||
|
||||
if (tagName === "webview") {
|
||||
const view = createElement("iframe") as HTMLIFrameElement;
|
||||
view.style.border = "0px";
|
||||
@ -56,8 +100,19 @@ const newCreateElement = <K extends keyof HTMLElementTagNameMap>(tagName: K): HT
|
||||
view.contentDocument.body.parentElement!.style.overflow = "hidden";
|
||||
const script = createElement("script");
|
||||
script.src = url;
|
||||
script.addEventListener("load", () => {
|
||||
view.contentDocument!.dispatchEvent(new Event("DOMContentLoaded", {
|
||||
bubbles: true,
|
||||
cancelable: true,
|
||||
}));
|
||||
// const e = new CustomEvent("ipc-message");
|
||||
// (e as any).channel = "webview-ready"; // tslint:disable-line no-any
|
||||
// (e as any).args = [frameID]; // tslint:disable-line no-any
|
||||
// view.dispatchEvent(e);
|
||||
});
|
||||
view.contentDocument.head.appendChild(script);
|
||||
}
|
||||
|
||||
};
|
||||
},
|
||||
});
|
||||
@ -65,8 +120,8 @@ const newCreateElement = <K extends keyof HTMLElementTagNameMap>(tagName: K): HT
|
||||
(view as any).send = (channel: string, ...args: any[]): void => { // tslint:disable-line no-any
|
||||
if (args[0] && typeof args[0] === "object" && args[0].contents) {
|
||||
// TODO
|
||||
// args[0].contents = (args[0].contents as string).replace(/"(file:\/\/[^"]*)"/g, (m) => `"${getFetchUrl(m)}"`);
|
||||
// args[0].contents = (args[0].contents as string).replace(/"vscode-resource:([^"]*)"/g, (m) => `"${getFetchUrl(m)}"`);
|
||||
args[0].contents = (args[0].contents as string).replace(/"(file:\/\/[^"]*)"/g, (m1) => `"/resource${m1}"`);
|
||||
args[0].contents = (args[0].contents as string).replace(/"vscode-resource:([^"]*)"/g, (m, m1) => `"/resource${m1}"`);
|
||||
}
|
||||
if (view.contentWindow) {
|
||||
view.contentWindow.postMessage({
|
||||
|
@ -118,6 +118,7 @@ class FS {
|
||||
const str = fs.createWriteStream(path, options);
|
||||
ae.on("write", (d: string) => str.write(_Buffer.from(d, "utf8")));
|
||||
ae.on("close", () => str.close());
|
||||
ae.on("destroy", () => str.destroy());
|
||||
str.on("close", () => ae.emit("close"));
|
||||
str.on("open", (fd) => ae.emit("open", fd));
|
||||
str.on("error", (err) => ae.emit(err));
|
||||
@ -157,6 +158,10 @@ class FS {
|
||||
ae.emit("close");
|
||||
}
|
||||
|
||||
public destroy(): void {
|
||||
ae.emit("destroy");
|
||||
}
|
||||
|
||||
}) as fs.WriteStream;
|
||||
}
|
||||
|
||||
|
@ -32,6 +32,10 @@ class OS {
|
||||
this._tmpdir = data.tmpDirectory;
|
||||
}
|
||||
|
||||
public release(): string {
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
public platform(): NodeJS.Platform {
|
||||
if (navigator.appVersion.indexOf("Win") != -1) {
|
||||
return "win32";
|
||||
|
4
packages/runner/package.json
Normal file
4
packages/runner/package.json
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"name": "@coder/runner",
|
||||
"main": "src/index.ts"
|
||||
}
|
1
packages/runner/src/index.ts
Normal file
1
packages/runner/src/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from "./runner";
|
114
packages/runner/src/runner.ts
Normal file
114
packages/runner/src/runner.ts
Normal file
@ -0,0 +1,114 @@
|
||||
import * as cp from "child_process";
|
||||
import { logger, Logger, field, time } from "@coder/logger";
|
||||
|
||||
export interface CommandResult {
|
||||
readonly exitCode: number;
|
||||
readonly stdout: string;
|
||||
readonly stderr: string;
|
||||
}
|
||||
|
||||
const execute = (command: string, args: string[] = [], options: cp.SpawnOptions, logger: Logger): Promise<CommandResult> => {
|
||||
let resolve: (result: CommandResult) => void;
|
||||
const prom = new Promise<CommandResult>(res => resolve = res);
|
||||
|
||||
const stdout: string[] = [];
|
||||
const stderr: string[] = [];
|
||||
const complete = (exitCode: number): void => {
|
||||
resolve({
|
||||
stderr: stderr.join(""),
|
||||
stdout: stdout.join(""),
|
||||
exitCode,
|
||||
});
|
||||
};
|
||||
logger.info(`Executing '${command} ${JSON.stringify(args)}'`, field("options", options));
|
||||
const proc = cp.spawn(command, args.length > 0 ? args : [], options);
|
||||
proc.on("close", (code) => {
|
||||
complete(code);
|
||||
});
|
||||
proc.on("exit", (code) => {
|
||||
complete(code!);
|
||||
});
|
||||
proc.stdout.on("data", (d) => {
|
||||
stdout.push(d.toString());
|
||||
logger.debug("stdio", field("stdout", d.toString()));
|
||||
});
|
||||
proc.stderr.on("data", (d) => {
|
||||
stderr.push(d.toString());
|
||||
logger.debug("stdio", field("stderr", d.toString()));
|
||||
});
|
||||
|
||||
return prom;
|
||||
};
|
||||
|
||||
export type TaskFunction = (runner: Runner) => void | Promise<void>;
|
||||
|
||||
export interface Runner {
|
||||
|
||||
cwd: string;
|
||||
execute(command: string, args?: string[], env?: object): Promise<CommandResult>;
|
||||
}
|
||||
|
||||
export interface Task {
|
||||
readonly name: string;
|
||||
readonly func: TaskFunction;
|
||||
}
|
||||
|
||||
const tasks = new Map<string, Task>();
|
||||
const activated = new Map<string, Promise<void>>();
|
||||
|
||||
export const register = (name: string, func: TaskFunction): () => void | Promise<void> => {
|
||||
if (tasks.has(name)) {
|
||||
throw new Error(`Task "${name}" already registered`);
|
||||
}
|
||||
|
||||
tasks.set(name, {
|
||||
name,
|
||||
func,
|
||||
});
|
||||
|
||||
return (): void | Promise<void> => {
|
||||
return run(name);
|
||||
};
|
||||
};
|
||||
|
||||
export const run = (name: string = process.argv[2]): void | Promise<void> => {
|
||||
const task = tasks.get(name);
|
||||
if (!task) {
|
||||
logger.error("Task not found.", field("name", name), field("available", Array.from(tasks.keys())));
|
||||
|
||||
return process.exit(1);
|
||||
}
|
||||
if (activated.has(name)) {
|
||||
return activated.get(name);
|
||||
}
|
||||
let cwd: string = process.cwd();
|
||||
const log = logger.named(name);
|
||||
const timer = time(Number.MAX_SAFE_INTEGER);
|
||||
log.info("Starting...");
|
||||
const prom = task.func({
|
||||
set cwd(path: string) {
|
||||
cwd = path;
|
||||
},
|
||||
execute(command: string, args: string[] = [], env?: object): Promise<CommandResult> {
|
||||
return execute(command, args, {
|
||||
cwd,
|
||||
env: env as NodeJS.ProcessEnv,
|
||||
}, log);
|
||||
},
|
||||
});
|
||||
|
||||
if (prom) {
|
||||
activated.set(name, prom);
|
||||
prom.then(() => {
|
||||
log.info("Completed!", field("time", timer));
|
||||
}).catch((ex) => {
|
||||
activated.delete(name);
|
||||
log.error(`Failed: ${ex.message}`);
|
||||
log.error(`Stack: ${ex.stack}`);
|
||||
|
||||
return process.exit(1);
|
||||
});
|
||||
}
|
||||
|
||||
return prom;
|
||||
};
|
4
packages/runner/yarn.lock
Normal file
4
packages/runner/yarn.lock
Normal file
@ -0,0 +1,4 @@
|
||||
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
|
||||
# yarn lockfile v1
|
||||
|
||||
|
16
packages/server/README.md
Normal file
16
packages/server/README.md
Normal file
@ -0,0 +1,16 @@
|
||||
# server
|
||||
|
||||
## Endpoints
|
||||
|
||||
### `/tunnel/<port>`
|
||||
|
||||
Tunnels a TCP connection over WebSockets. Implemented for proxying connections from a remote machine locally.
|
||||
|
||||
### `/ports`
|
||||
|
||||
Watches for open ports. Implemented for tunneling ports on the remote server.
|
||||
|
||||
### `/resource/<url>`
|
||||
|
||||
Reads files on GET.
|
||||
Writes files on POST.
|
@ -18,9 +18,12 @@
|
||||
"@oclif/plugin-help": "^2.1.4",
|
||||
"express": "^4.16.4",
|
||||
"express-static-gzip": "^1.1.3",
|
||||
"httpolyglot": "^0.1.2",
|
||||
"mime-types": "^2.1.21",
|
||||
"nexe": "^2.0.0-rc.34",
|
||||
"segfault-handler": "^1.0.1",
|
||||
"node-netstat": "^1.6.0",
|
||||
"pem": "^1.14.1",
|
||||
"promise.prototype.finally": "^3.1.0",
|
||||
"spdlog": "^0.7.2",
|
||||
"ws": "^6.1.2",
|
||||
"xhr2": "^0.1.4"
|
||||
@ -29,6 +32,7 @@
|
||||
"@types/express": "^4.16.0",
|
||||
"@types/fs-extra": "^5.0.4",
|
||||
"@types/mime-types": "^2.1.0",
|
||||
"@types/pem": "^1.9.4",
|
||||
"@types/ws": "^6.0.1",
|
||||
"fs-extra": "^7.0.1",
|
||||
"string-replace-webpack-plugin": "^0.1.3",
|
||||
|
@ -3,57 +3,12 @@ const fse = require("fs-extra");
|
||||
const os = require("os");
|
||||
const path = require("path");
|
||||
const nexe = require("nexe");
|
||||
const zlib = require("zlib");
|
||||
|
||||
const nexeRoot = path.join(os.homedir(), ".nexe");
|
||||
if (!fs.existsSync(nexeRoot)) {
|
||||
throw new Error("run nexe manually on a binary to initialize it");
|
||||
}
|
||||
const listed = fs.readdirSync(nexeRoot);
|
||||
listed.forEach((list) => {
|
||||
if (list.startsWith("linux")) {
|
||||
const stat = fs.statSync(path.join(nexeRoot, list));
|
||||
if (stat.isFile()) {
|
||||
if (stat.size > 20000000) {
|
||||
throw new Error("must use upx to shrink node binary in ~/.nexe/" + list);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const tmpDir = path.join(__dirname, "../build");
|
||||
if (fs.existsSync(tmpDir)) {
|
||||
console.log("Removing old build dir...");
|
||||
fse.removeSync(tmpDir);
|
||||
}
|
||||
|
||||
console.log("Copying build files...");
|
||||
fse.copySync(path.join(__dirname, "../resources"), tmpDir, {
|
||||
recursive: true,
|
||||
});
|
||||
const modDir = path.join(tmpDir, "modules");
|
||||
fs.mkdirSync(modDir);
|
||||
fse.copySync(path.join(__dirname, "../../protocol/node_modules/node-pty/build/Release/pty.node"), path.join(modDir, "pty.node"));
|
||||
|
||||
const zipper = (p) => {
|
||||
const stat = fs.statSync(p);
|
||||
if (!stat.isDirectory()) {
|
||||
fs.writeFileSync(p + ".gz", zlib.gzipSync(fs.readFileSync(p)));
|
||||
fse.removeSync(p);
|
||||
return;
|
||||
}
|
||||
const files = fs.readdirSync(p);
|
||||
files.forEach((f) => zipper(path.join(p, f)));
|
||||
};
|
||||
|
||||
zipper(path.join(tmpDir, "web"));
|
||||
zipper(path.join(tmpDir, "bootstrap-fork.js"));
|
||||
|
||||
nexe.compile({
|
||||
debugBundle: true,
|
||||
input: path.join(__dirname, "../out/cli.js"),
|
||||
output: 'cli',
|
||||
targets: ["linux"],
|
||||
output: `cli-${process.env.TRAVIS_OS_NAME || os.platform()}`,
|
||||
targets: [os.platform()],
|
||||
native: {
|
||||
spdlog: {
|
||||
additionalFiles: [
|
||||
|
@ -6,7 +6,7 @@ import * as os from "os";
|
||||
import * as path from "path";
|
||||
import * as WebSocket from "ws";
|
||||
import { createApp } from "./server";
|
||||
import { requireModule } from "./vscode/bootstrapFork";
|
||||
import { requireModule, requireFork } from "./vscode/bootstrapFork";
|
||||
import { SharedProcess, SharedProcessState } from "./vscode/sharedProcess";
|
||||
import { setup as setupNativeModules } from "./modules";
|
||||
import { fillFs } from "./fill";
|
||||
@ -26,6 +26,8 @@ export class Entry extends Command {
|
||||
|
||||
// Dev flags
|
||||
"bootstrap-fork": flags.string({ hidden: true }),
|
||||
"fork": flags.string({ hidden: true }),
|
||||
|
||||
env: flags.string({ hidden: true }),
|
||||
args: flags.string({ hidden: true }),
|
||||
};
|
||||
@ -76,6 +78,12 @@ export class Entry extends Command {
|
||||
return requireModule(modulePath, builtInExtensionsDir);
|
||||
}
|
||||
|
||||
if (flags["fork"]) {
|
||||
const modulePath = flags["fork"];
|
||||
|
||||
return requireFork(modulePath, JSON.parse(flags.args!), builtInExtensionsDir);
|
||||
}
|
||||
|
||||
const dataDir = flags["data-dir"] || path.join(os.homedir(), ".vscode-remote");
|
||||
const workingDir = args["workdir"];
|
||||
|
||||
@ -92,6 +100,38 @@ export class Entry extends Command {
|
||||
const logDir = path.join(dataDir, "logs", new Date().toISOString().replace(/[-:.TZ]/g, ""));
|
||||
process.env.VSCODE_LOGS = logDir;
|
||||
|
||||
const certPath = flags.cert;
|
||||
const certKeyPath = flags["cert-key"];
|
||||
|
||||
if (certPath && !certKeyPath) {
|
||||
logger.error("'--cert-key' flag is required when specifying a certificate!");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (!certPath && certKeyPath) {
|
||||
logger.error("'--cert' flag is required when specifying certificate key!");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
let certData: Buffer | undefined;
|
||||
let certKeyData: Buffer | undefined;
|
||||
|
||||
if (typeof certPath !== "undefined" && typeof certKeyPath !== "undefined") {
|
||||
try {
|
||||
certData = fs.readFileSync(certPath);
|
||||
} catch (ex) {
|
||||
logger.error(`Failed to read certificate: ${ex.message}`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
try {
|
||||
certKeyData = fs.readFileSync(certKeyPath);
|
||||
} catch (ex) {
|
||||
logger.error(`Failed to read certificate key: ${ex.message}`);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
logger.info("\u001B[1mvscode-remote v1.0.0");
|
||||
// TODO: fill in appropriate doc url
|
||||
logger.info("Additional documentation: https://coder.com/docs");
|
||||
@ -111,7 +151,9 @@ export class Entry extends Command {
|
||||
}
|
||||
});
|
||||
|
||||
const app = createApp((app) => {
|
||||
const password = "023450wf0951";
|
||||
const hasCustomHttps = certData && certKeyData;
|
||||
const app = await createApp((app) => {
|
||||
app.use((req, res, next) => {
|
||||
res.on("finish", () => {
|
||||
logger.trace(`\u001B[1m${req.method} ${res.statusCode} \u001B[0m${req.url}`, field("host", req.hostname), field("ip", req.ip));
|
||||
@ -135,7 +177,10 @@ export class Entry extends Command {
|
||||
builtInExtensionsDirectory: builtInExtensionsDir,
|
||||
dataDirectory: dataDir,
|
||||
workingDirectory: workingDir,
|
||||
});
|
||||
}, password, hasCustomHttps ? {
|
||||
key: certKeyData,
|
||||
cert: certData,
|
||||
} : undefined);
|
||||
|
||||
logger.info("Starting webserver...", field("host", flags.host), field("port", flags.port));
|
||||
app.server.listen(flags.port, flags.host);
|
||||
@ -161,7 +206,7 @@ export class Entry extends Command {
|
||||
}
|
||||
|
||||
logger.info(" ");
|
||||
logger.info("Password:\u001B[1m 023450wf09");
|
||||
logger.info(`Password:\u001B[1m ${password}`);
|
||||
logger.info(" ");
|
||||
logger.info("Started (click the link below to open):");
|
||||
logger.info(`http://localhost:${flags.port}/`);
|
||||
|
@ -49,7 +49,11 @@ export const fillFs = (): void => {
|
||||
}
|
||||
};
|
||||
if (customPromisify) {
|
||||
(<any>fs[propertyName])[util.promisify.custom] = customPromisify;
|
||||
(<any>fs[propertyName])[util.promisify.custom] = (...args: any[]) => {
|
||||
return customPromisify(...args).catch((ex) => {
|
||||
throw ex;
|
||||
});
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
@ -113,13 +117,6 @@ export const fillFs = (): void => {
|
||||
|
||||
const fileDesc = fds.get(fd)!;
|
||||
|
||||
/**
|
||||
* `readFile` is filled within nexe, but `read` is not
|
||||
* https://github.com/nexe/nexe/blob/master/src/fs/patch.ts#L199
|
||||
* We can simulate a real _read_ by reading the entire file.
|
||||
* Efficiency can be improved here by storing the entire file in memory
|
||||
* until it has been closed.
|
||||
*/
|
||||
return fs.readFile(fileDesc.path, (err, rb) => {
|
||||
if (err) {
|
||||
return callOld();
|
||||
|
@ -35,8 +35,10 @@ export const setup = (dataDirectory: string): void => {
|
||||
*/
|
||||
unpackModule("pty");
|
||||
const nodePtyUtils = require("../../protocol/node_modules/node-pty/lib/utils") as typeof import("../../protocol/node_modules/node-pty/src/utils");
|
||||
nodePtyUtils.loadNative = (modName: string) => {
|
||||
// tslint:disable-next-line:no-any
|
||||
nodePtyUtils.loadNative = (modName: string): any => {
|
||||
return __non_webpack_require__(path.join(dataDirectory, "modules", modName + ".node"));
|
||||
};
|
||||
// tslint:disable-next-line:no-unused-expression
|
||||
require("../../protocol/node_modules/node-pty/lib/index") as typeof import("../../protocol/node_modules/node-pty/src/index");
|
||||
};
|
||||
|
105
packages/server/src/portScanner.ts
Normal file
105
packages/server/src/portScanner.ts
Normal file
@ -0,0 +1,105 @@
|
||||
//@ts-ignore
|
||||
import * as netstat from "node-netstat";
|
||||
import { Event, Emitter } from "@coder/events";
|
||||
|
||||
export interface PortScanner {
|
||||
readonly ports: ReadonlyArray<number>;
|
||||
|
||||
readonly onAdded: Event<ReadonlyArray<number>>;
|
||||
readonly onRemoved: Event<ReadonlyArray<number>>;
|
||||
|
||||
dispose(): void;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a disposable port scanner.
|
||||
* Will scan local ports and emit events when ports are added or removed.
|
||||
* Currently only scans TCP ports.
|
||||
*/
|
||||
export const createPortScanner = (scanInterval: number = 250): PortScanner => {
|
||||
const ports = new Map<number, number>();
|
||||
|
||||
const addEmitter = new Emitter<number[]>();
|
||||
const removeEmitter = new Emitter<number[]>();
|
||||
|
||||
const scan = (onCompleted: (err?: Error) => void): void => {
|
||||
const scanTime = Date.now();
|
||||
const added: number[] = [];
|
||||
netstat({
|
||||
done: (err: Error): void => {
|
||||
const removed: number[] = [];
|
||||
ports.forEach((value, key) => {
|
||||
if (value !== scanTime) {
|
||||
// Remove port
|
||||
removed.push(key);
|
||||
ports.delete(key);
|
||||
}
|
||||
});
|
||||
if (removed.length > 0) {
|
||||
removeEmitter.emit(removed);
|
||||
}
|
||||
|
||||
if (added.length > 0) {
|
||||
addEmitter.emit(added);
|
||||
}
|
||||
|
||||
onCompleted(err);
|
||||
},
|
||||
filter: {
|
||||
state: "LISTEN",
|
||||
},
|
||||
}, (data: {
|
||||
readonly protocol: string;
|
||||
readonly local: {
|
||||
readonly port: number;
|
||||
readonly address: string;
|
||||
};
|
||||
}) => {
|
||||
// https://en.wikipedia.org/wiki/Registered_port
|
||||
if (data.local.port <= 1023 || data.local.port >= 49151) {
|
||||
return;
|
||||
}
|
||||
// Only forward TCP ports
|
||||
if (!data.protocol.startsWith("tcp")) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ports.has(data.local.port)) {
|
||||
added.push(data.local.port);
|
||||
}
|
||||
ports.set(data.local.port, scanTime);
|
||||
});
|
||||
};
|
||||
|
||||
let lastTimeout: NodeJS.Timer | undefined;
|
||||
let disposed: boolean = false;
|
||||
|
||||
const doInterval = (): void => {
|
||||
scan(() => {
|
||||
if (disposed) {
|
||||
return;
|
||||
}
|
||||
lastTimeout = setTimeout(doInterval, scanInterval);
|
||||
});
|
||||
};
|
||||
|
||||
doInterval();
|
||||
|
||||
return {
|
||||
get ports(): number[] {
|
||||
return Array.from(ports.keys());
|
||||
},
|
||||
get onAdded(): Event<number[]> {
|
||||
return addEmitter.event;
|
||||
},
|
||||
get onRemoved(): Event<number[]> {
|
||||
return removeEmitter.event;
|
||||
},
|
||||
dispose(): void {
|
||||
if (typeof lastTimeout !== "undefined") {
|
||||
clearTimeout(lastTimeout);
|
||||
}
|
||||
disposed = true;
|
||||
},
|
||||
};
|
||||
};
|
@ -1,4 +1,4 @@
|
||||
import { logger } from "@coder/logger";
|
||||
import { logger, field } from "@coder/logger";
|
||||
import { ReadWriteConnection } from "@coder/protocol";
|
||||
import { Server, ServerOptions } from "@coder/protocol/src/node/server";
|
||||
import * as express from "express";
|
||||
@ -6,30 +6,116 @@ import * as express from "express";
|
||||
import * as expressStaticGzip from "express-static-gzip";
|
||||
import * as fs from "fs";
|
||||
import * as http from "http";
|
||||
//@ts-ignore
|
||||
import * as httpolyglot from "httpolyglot";
|
||||
import * as https from "https";
|
||||
import * as mime from "mime-types";
|
||||
import * as net from "net";
|
||||
import * as path from "path";
|
||||
import * as pem from "pem";
|
||||
import * as util from "util";
|
||||
import * as ws from "ws";
|
||||
import { isCli, buildDir } from "./constants";
|
||||
import { TunnelCloseCode } from "@coder/tunnel/src/common";
|
||||
import { handle as handleTunnel } from "@coder/tunnel/src/server";
|
||||
import { createPortScanner } from "./portScanner";
|
||||
import { buildDir, isCli } from "./constants";
|
||||
|
||||
export const createApp = (registerMiddleware?: (app: express.Application) => void, options?: ServerOptions): {
|
||||
export const createApp = async (registerMiddleware?: (app: express.Application) => void, options?: ServerOptions, password?: string, httpsOptions?: https.ServerOptions): Promise<{
|
||||
readonly express: express.Application;
|
||||
readonly server: http.Server;
|
||||
readonly wss: ws.Server;
|
||||
} => {
|
||||
}> => {
|
||||
const parseCookies = (req: http.IncomingMessage): { [key: string]: string } => {
|
||||
const cookies: { [key: string]: string } = {};
|
||||
const rc = req.headers.cookie;
|
||||
if (rc) {
|
||||
rc.split(";").forEach((cook) => {
|
||||
const parts = cook.split("=");
|
||||
cookies[parts.shift()!.trim()] = decodeURI(parts.join("="));
|
||||
});
|
||||
}
|
||||
|
||||
return cookies;
|
||||
};
|
||||
|
||||
const isAuthed = (req: http.IncomingMessage): boolean => {
|
||||
try {
|
||||
if (!password || !isCli) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Try/catch placed here just in case
|
||||
const cookies = parseCookies(req);
|
||||
if (cookies.password && cookies.password === password) {
|
||||
return true;
|
||||
}
|
||||
} catch (ex) {
|
||||
logger.error("Failed to parse cookies", field("error", ex));
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
const isEncrypted = (socket: net.Socket): boolean => {
|
||||
// tslint:disable-next-line:no-any
|
||||
return (socket as any).encrypted;
|
||||
};
|
||||
|
||||
const app = express();
|
||||
if (registerMiddleware) {
|
||||
registerMiddleware(app);
|
||||
}
|
||||
const server = http.createServer(app);
|
||||
|
||||
const certs = await new Promise<pem.CertificateCreationResult>((res, rej): void => {
|
||||
pem.createCertificate({
|
||||
selfSigned: true,
|
||||
}, (err, result) => {
|
||||
if (err) {
|
||||
rej(err);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
res(result);
|
||||
});
|
||||
});
|
||||
|
||||
const server = httpolyglot.createServer({
|
||||
key: certs.serviceKey,
|
||||
cert: certs.certificate,
|
||||
}, app) as http.Server;
|
||||
const wss = new ws.Server({ server });
|
||||
|
||||
wss.shouldHandle = (req): boolean => {
|
||||
// Should handle auth here
|
||||
return true;
|
||||
return isAuthed(req);
|
||||
};
|
||||
|
||||
wss.on("connection", (ws) => {
|
||||
const portScanner = createPortScanner();
|
||||
wss.on("connection", (ws, req) => {
|
||||
if (req.url && req.url.startsWith("/tunnel")) {
|
||||
try {
|
||||
const rawPort = req.url.split("/").pop();
|
||||
const port = Number.parseInt(rawPort!, 10);
|
||||
|
||||
handleTunnel(ws, port);
|
||||
} catch (ex) {
|
||||
ws.close(TunnelCloseCode.Error, ex.toString());
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (req.url && req.url.startsWith("/ports")) {
|
||||
const onAdded = portScanner.onAdded((added) => ws.send(JSON.stringify({ added })));
|
||||
const onRemoved = portScanner.onRemoved((removed) => ws.send(JSON.stringify({ removed })));
|
||||
ws.on("close", () => {
|
||||
onAdded.dispose();
|
||||
onRemoved.dispose();
|
||||
});
|
||||
|
||||
return ws.send(JSON.stringify({ ports: portScanner.ports }));
|
||||
}
|
||||
|
||||
const connection: ReadWriteConnection = {
|
||||
onMessage: (cb): void => {
|
||||
ws.addEventListener("message", (event) => cb(event.data));
|
||||
@ -52,11 +138,17 @@ export const createApp = (registerMiddleware?: (app: express.Application) => voi
|
||||
});
|
||||
|
||||
const baseDir = buildDir || path.join(__dirname, "..");
|
||||
if (isCli) {
|
||||
app.use(expressStaticGzip(path.join(baseDir, "build/web")));
|
||||
const authStaticFunc = expressStaticGzip(path.join(baseDir, "build/web/auth"));
|
||||
const unauthStaticFunc = expressStaticGzip(path.join(baseDir, "build/web/unauth"));
|
||||
app.use((req, res, next) => {
|
||||
if (isAuthed(req)) {
|
||||
// We can serve the actual VSCode bin
|
||||
authStaticFunc(req, res, next);
|
||||
} else {
|
||||
app.use(express.static(path.join(baseDir, "resources/web")));
|
||||
// Serve only the unauthed version
|
||||
unauthStaticFunc(req, res, next);
|
||||
}
|
||||
});
|
||||
app.get("/resource/:url(*)", async (req, res) => {
|
||||
try {
|
||||
const fullPath = `/${req.params.url}`;
|
||||
@ -91,6 +183,28 @@ export const createApp = (registerMiddleware?: (app: express.Application) => voi
|
||||
res.end();
|
||||
}
|
||||
});
|
||||
app.post("/resource/:url(*)", async (req, res) => {
|
||||
try {
|
||||
const fullPath = `/${req.params.url}`;
|
||||
|
||||
const data: string[] = [];
|
||||
req.setEncoding("utf8");
|
||||
req.on("data", (chunk) => {
|
||||
data.push(chunk);
|
||||
});
|
||||
req.on("end", () => {
|
||||
const body = data.join("");
|
||||
fs.writeFileSync(fullPath, body);
|
||||
logger.debug("Wrote resource", field("path", fullPath), field("content-length", body.length));
|
||||
res.status(200);
|
||||
res.end();
|
||||
});
|
||||
} catch (ex) {
|
||||
res.write(ex.toString());
|
||||
res.status(500);
|
||||
res.end();
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
express: app,
|
||||
|
@ -5,37 +5,104 @@ import * as zlib from "zlib";
|
||||
import * as vm from "vm";
|
||||
import { isCli } from "../constants";
|
||||
|
||||
export const requireModule = (modulePath: string, builtInExtensionsDir: string): void => {
|
||||
process.env.AMD_ENTRYPOINT = modulePath;
|
||||
const xml = require("xhr2");
|
||||
// tslint:disable-next-line no-any this makes installing extensions work.
|
||||
(global as any).XMLHttpRequest = xml.XMLHttpRequest;
|
||||
let ipcMsgBuffer: Buffer[] | undefined = [];
|
||||
let ipcMsgListener = process.send ? (d: Buffer): number => ipcMsgBuffer!.push(d) : undefined;
|
||||
if (ipcMsgListener) {
|
||||
process.on("message", ipcMsgListener);
|
||||
}
|
||||
|
||||
const mod = require("module") as typeof import("module");
|
||||
/**
|
||||
* Used for loading extensions. Using __non_webpack_require__ didn't work
|
||||
* as it was not resolving to the FS.
|
||||
/**
|
||||
* Requires a module from the filesystem.
|
||||
*
|
||||
* Will load from the CLI if file is included inside of the default extensions dir
|
||||
*/
|
||||
(global as any).nativeNodeRequire = (id: string): any => {// tslint:disable-line no-any
|
||||
// tslint:disable-next-line:no-any
|
||||
const requireFilesystemModule = (id: string, builtInExtensionsDir: string): any => {
|
||||
const mod = require("module") as typeof import("module");
|
||||
const customMod = new mod.Module(id);
|
||||
customMod.filename = id;
|
||||
// tslint:disable-next-line no-any
|
||||
customMod.paths = (mod as any)._nodeModulePaths(path.dirname(id));
|
||||
// tslint:disable-next-line:no-any
|
||||
customMod.paths = [(<any>mod)._nodeModulePaths(path.dirname(id)), path.join(__dirname, "../../../../lib/vscode/node_modules")];
|
||||
|
||||
if (id.startsWith(builtInExtensionsDir)) {
|
||||
customMod.loaded = true;
|
||||
const req = vm.runInThisContext(mod.wrap(fs.readFileSync(id + ".js").toString()), {
|
||||
const fileName = id.endsWith(".js") ? id : `${id}.js`;
|
||||
const req = vm.runInThisContext(mod.wrap(fs.readFileSync(fileName).toString()), {
|
||||
displayErrors: true,
|
||||
filename: id + ".js",
|
||||
filename: id + fileName,
|
||||
});
|
||||
req(customMod.exports, customMod.require.bind(customMod), customMod, __filename, path.dirname(id));
|
||||
req(customMod.exports, customMod.require.bind(customMod), customMod, fileName, path.dirname(id));
|
||||
|
||||
return customMod.exports;
|
||||
}
|
||||
|
||||
return customMod.require(id);
|
||||
};
|
||||
|
||||
/**
|
||||
* Called from forking a module
|
||||
*/
|
||||
export const requireFork = (modulePath: string, args: string[], builtInExtensionsDir: string): void => {
|
||||
const Module = require("module") as typeof import("module");
|
||||
const oldRequire = Module.prototype.require;
|
||||
// tslint:disable-next-line:no-any
|
||||
Module.prototype.require = (id: string): any => {
|
||||
if (id === "typescript") {
|
||||
return require("typescript");
|
||||
}
|
||||
|
||||
return oldRequire(id);
|
||||
};
|
||||
|
||||
if (!process.send) {
|
||||
throw new Error("No IPC messaging initialized");
|
||||
}
|
||||
|
||||
process.argv = ["", "", ...args];
|
||||
|
||||
requireFilesystemModule(modulePath, builtInExtensionsDir);
|
||||
|
||||
if (ipcMsgBuffer && ipcMsgListener) {
|
||||
process.removeListener("message", ipcMsgListener);
|
||||
// tslint:disable-next-line:no-any
|
||||
ipcMsgBuffer.forEach((i) => process.emit("message" as any, i as any));
|
||||
ipcMsgBuffer = undefined;
|
||||
ipcMsgListener = undefined;
|
||||
}
|
||||
};
|
||||
|
||||
export const requireModule = (modulePath: string, builtInExtensionsDir: string): void => {
|
||||
process.env.AMD_ENTRYPOINT = modulePath;
|
||||
const xml = require("xhr2");
|
||||
xml.XMLHttpRequest.prototype._restrictedHeaders["user-agent"] = false;
|
||||
// tslint:disable-next-line no-any this makes installing extensions work.
|
||||
(global as any).XMLHttpRequest = xml.XMLHttpRequest;
|
||||
|
||||
const mod = require("module") as typeof import("module");
|
||||
const promiseFinally = require("promise.prototype.finally") as { shim: () => void };
|
||||
promiseFinally.shim();
|
||||
/**
|
||||
* Used for loading extensions. Using __non_webpack_require__ didn't work
|
||||
* as it was not resolving to the FS.
|
||||
*/
|
||||
// tslint:disable-next-line:no-any
|
||||
(global as any).nativeNodeRequire = (id: string): any => {
|
||||
return requireFilesystemModule(id, builtInExtensionsDir);
|
||||
};
|
||||
|
||||
if (isCli) {
|
||||
/**
|
||||
* Needed for properly forking external modules within the CLI
|
||||
*/
|
||||
// tslint:disable-next-line:no-any
|
||||
(<any>cp).fork = (modulePath: string, args: ReadonlyArray<string> = [], options?: cp.ForkOptions): cp.ChildProcess => {
|
||||
return cp.spawn(process.execPath, ["--fork", modulePath, "--args", JSON.stringify(args)], {
|
||||
...options,
|
||||
stdio: [null, null, null, "ipc"],
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
let content: Buffer | undefined;
|
||||
const readFile = (name: string): Buffer => {
|
||||
return fs.readFileSync(path.join(process.env.BUILD_DIR as string || path.join(__dirname, "../.."), "./build", name));
|
||||
@ -43,7 +110,7 @@ export const requireModule = (modulePath: string, builtInExtensionsDir: string):
|
||||
if (isCli) {
|
||||
content = zlib.gunzipSync(readFile("bootstrap-fork.js.gz"));
|
||||
} else {
|
||||
content = readFile("../resources/bootstrap-fork.js");
|
||||
content = readFile("../../vscode/bin/bootstrap-fork.js");
|
||||
}
|
||||
eval(content.toString());
|
||||
};
|
||||
@ -71,7 +138,7 @@ export const forkModule = (modulePath: string, args: string[], options: cp.ForkO
|
||||
stdio: [null, null, null, "ipc"],
|
||||
};
|
||||
if (isCli) {
|
||||
proc = cp.execFile(process.execPath, forkArgs, forkOptions);
|
||||
proc = cp.spawn(process.execPath, forkArgs, options);
|
||||
} else {
|
||||
proc = cp.spawn(process.execPath, ["--require", "ts-node/register", "--require", "tsconfig-paths/register", process.argv[1], ...forkArgs], forkOptions);
|
||||
}
|
||||
|
@ -129,6 +129,13 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-10.12.18.tgz#1d3ca764718915584fcd9f6344621b7672665c67"
|
||||
integrity sha512-fh+pAqt4xRzPfqA6eh3Z2y6fyZavRIumvjhaCL753+TVkGKGhpPeyrJG2JftD0T9q4GF00KjefsQ+PQNDdWQaQ==
|
||||
|
||||
"@types/pem@^1.9.4":
|
||||
version "1.9.4"
|
||||
resolved "https://registry.yarnpkg.com/@types/pem/-/pem-1.9.4.tgz#9ef9302dc5f0352503e193003b208cddef4ffa45"
|
||||
integrity sha512-cLRUgpedqF4lnQxDsjbRCgHRPHaJvnsHC+LEBTKnChddoPYJYQMq/LjSsEDwvRteeJV8MGt7Ea9jYCBVufrcNg==
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/range-parser@*":
|
||||
version "1.2.3"
|
||||
resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.3.tgz#7ee330ba7caafb98090bece86a5ee44115904c2c"
|
||||
@ -430,13 +437,6 @@ binary-extensions@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.12.0.tgz#c2d780f53d45bba8317a8902d4ceeaf3a6385b14"
|
||||
integrity sha512-DYWGk01lDcxeS/K9IHPGWfT8PsJmbXRtRd2Sx72Tnb8pcYZQFF1oSDb8hJtS1vhp212q1Rzi5dUf9+nq0o9UIg==
|
||||
|
||||
bindings@^1.2.1:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.4.0.tgz#909efa49f2ebe07ecd3cb136778f665052040127"
|
||||
integrity sha512-7znEVX22Djn+nYjxCWKDne0RRloa9XfYa84yk3s+HkE3LpDYZmhArYr9O9huBoHY3/oXispx5LorIX7Sl2CgSQ==
|
||||
dependencies:
|
||||
file-uri-to-path "1.0.0"
|
||||
|
||||
bindings@^1.3.0:
|
||||
version "1.3.1"
|
||||
resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.3.1.tgz#21fc7c6d67c18516ec5aaa2815b145ff77b26ea5"
|
||||
@ -624,6 +624,11 @@ chardet@^0.4.0:
|
||||
resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.4.2.tgz#b5473b33dc97c424e5d98dc87d55d4d8a29c8bf2"
|
||||
integrity sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=
|
||||
|
||||
charenc@~0.0.1:
|
||||
version "0.0.2"
|
||||
resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667"
|
||||
integrity sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc=
|
||||
|
||||
chokidar@^1.6.1:
|
||||
version "1.7.0"
|
||||
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-1.7.0.tgz#798e689778151c8076b4b360e5edd28cda2bb468"
|
||||
@ -800,6 +805,11 @@ core-util-is@1.0.2, core-util-is@~1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
|
||||
integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=
|
||||
|
||||
crypt@~0.0.1:
|
||||
version "0.0.2"
|
||||
resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b"
|
||||
integrity sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs=
|
||||
|
||||
css-loader@^0.9.1:
|
||||
version "0.9.1"
|
||||
resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-0.9.1.tgz#2e1aa00ce7e30ef2c6a7a4b300a080a7c979e0dc"
|
||||
@ -915,6 +925,13 @@ deepmerge@^2.0.1:
|
||||
resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-2.2.1.tgz#5d3ff22a01c00f645405a2fbc17d0778a1801170"
|
||||
integrity sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA==
|
||||
|
||||
define-properties@^1.1.2:
|
||||
version "1.1.3"
|
||||
resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1"
|
||||
integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==
|
||||
dependencies:
|
||||
object-keys "^1.0.12"
|
||||
|
||||
define-property@^0.2.5:
|
||||
version "0.2.5"
|
||||
resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116"
|
||||
@ -1019,6 +1036,32 @@ end-of-stream@^1.0.0:
|
||||
dependencies:
|
||||
once "^1.4.0"
|
||||
|
||||
es-abstract@^1.9.0:
|
||||
version "1.13.0"
|
||||
resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.13.0.tgz#ac86145fdd5099d8dd49558ccba2eaf9b88e24e9"
|
||||
integrity sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg==
|
||||
dependencies:
|
||||
es-to-primitive "^1.2.0"
|
||||
function-bind "^1.1.1"
|
||||
has "^1.0.3"
|
||||
is-callable "^1.1.4"
|
||||
is-regex "^1.0.4"
|
||||
object-keys "^1.0.12"
|
||||
|
||||
es-to-primitive@^1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.0.tgz#edf72478033456e8dda8ef09e00ad9650707f377"
|
||||
integrity sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==
|
||||
dependencies:
|
||||
is-callable "^1.1.4"
|
||||
is-date-object "^1.0.1"
|
||||
is-symbol "^1.0.2"
|
||||
|
||||
es6-promisify@^6.0.0:
|
||||
version "6.0.1"
|
||||
resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-6.0.1.tgz#6edaa45f3bd570ffe08febce66f7116be4b1cdb6"
|
||||
integrity sha512-J3ZkwbEnnO+fGAKrjVpeUAnZshAdfZvbhQpqfIH9kSAspReRC4nJnu8ewm55b4y9ElyeuhCTzJD0XiH8Tsbhlw==
|
||||
|
||||
escape-html@~1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988"
|
||||
@ -1279,11 +1322,6 @@ file-type@^6.1.0:
|
||||
resolved "https://registry.yarnpkg.com/file-type/-/file-type-6.2.0.tgz#e50cd75d356ffed4e306dc4f5bcf52a79903a919"
|
||||
integrity sha512-YPcTBDV+2Tm0VqjybVd32MHdlEGAtuxS3VAYsumFokDSMG+ROT5wawGlnHDoz7bfMcMDt9hxuXvXwoKUx2fkOg==
|
||||
|
||||
file-uri-to-path@1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd"
|
||||
integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==
|
||||
|
||||
filename-regex@^2.0.0:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26"
|
||||
@ -1429,6 +1467,11 @@ fsevents@^1.0.0:
|
||||
nan "^2.9.2"
|
||||
node-pre-gyp "^0.10.0"
|
||||
|
||||
function-bind@^1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
|
||||
integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==
|
||||
|
||||
fuse-box@^3.1.0:
|
||||
version "3.6.0"
|
||||
resolved "https://registry.yarnpkg.com/fuse-box/-/fuse-box-3.6.0.tgz#a4adf41a60855c7b0a0775b3095b6b0c2d35b011"
|
||||
@ -1645,6 +1688,11 @@ has-symbol-support-x@^1.4.1:
|
||||
resolved "https://registry.yarnpkg.com/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz#1409f98bc00247da45da67cee0a36f282ff26455"
|
||||
integrity sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw==
|
||||
|
||||
has-symbols@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.0.tgz#ba1a8f1af2a0fc39650f5c850367704122063b44"
|
||||
integrity sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=
|
||||
|
||||
has-to-string-tag-x@^1.2.0:
|
||||
version "1.4.1"
|
||||
resolved "https://registry.yarnpkg.com/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz#a045ab383d7b4b2012a00148ab0aa5f290044d4d"
|
||||
@ -1688,6 +1736,13 @@ has-values@^1.0.0:
|
||||
is-number "^3.0.0"
|
||||
kind-of "^4.0.0"
|
||||
|
||||
has@^1.0.1, has@^1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796"
|
||||
integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==
|
||||
dependencies:
|
||||
function-bind "^1.1.1"
|
||||
|
||||
http-cache-semantics@3.8.1:
|
||||
version "3.8.1"
|
||||
resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz#39b0e16add9b605bf0a9ef3d9daaf4843b4cacd2"
|
||||
@ -1712,6 +1767,11 @@ http-signature@~1.2.0:
|
||||
jsprim "^1.2.2"
|
||||
sshpk "^1.7.0"
|
||||
|
||||
httpolyglot@^0.1.2:
|
||||
version "0.1.2"
|
||||
resolved "https://registry.yarnpkg.com/httpolyglot/-/httpolyglot-0.1.2.tgz#e4d347fe8984a62f467d4060df527f1851f6997b"
|
||||
integrity sha1-5NNH/omEpi9GfUBg31J/GFH2mXs=
|
||||
|
||||
iconv-lite@0.4.23:
|
||||
version "0.4.23"
|
||||
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.23.tgz#297871f63be507adcfbfca715d0cd0eed84e9a63"
|
||||
@ -1815,11 +1875,16 @@ is-binary-path@^1.0.0:
|
||||
dependencies:
|
||||
binary-extensions "^1.0.0"
|
||||
|
||||
is-buffer@^1.1.5:
|
||||
is-buffer@^1.1.5, is-buffer@~1.1.1:
|
||||
version "1.1.6"
|
||||
resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be"
|
||||
integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==
|
||||
|
||||
is-callable@^1.1.4:
|
||||
version "1.1.4"
|
||||
resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75"
|
||||
integrity sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==
|
||||
|
||||
is-data-descriptor@^0.1.4:
|
||||
version "0.1.4"
|
||||
resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56"
|
||||
@ -1834,6 +1899,11 @@ is-data-descriptor@^1.0.0:
|
||||
dependencies:
|
||||
kind-of "^6.0.0"
|
||||
|
||||
is-date-object@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16"
|
||||
integrity sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=
|
||||
|
||||
is-descriptor@^0.1.0:
|
||||
version "0.1.6"
|
||||
resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca"
|
||||
@ -1956,6 +2026,13 @@ is-promise@^2.1.0:
|
||||
resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa"
|
||||
integrity sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=
|
||||
|
||||
is-regex@^1.0.4:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491"
|
||||
integrity sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=
|
||||
dependencies:
|
||||
has "^1.0.1"
|
||||
|
||||
is-retry-allowed@^1.0.0, is-retry-allowed@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz#11a060568b67339444033d0125a61a20d564fb34"
|
||||
@ -1966,6 +2043,13 @@ is-stream@^1.0.0, is-stream@^1.1.0:
|
||||
resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44"
|
||||
integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ=
|
||||
|
||||
is-symbol@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.2.tgz#a055f6ae57192caee329e7a860118b497a950f38"
|
||||
integrity sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==
|
||||
dependencies:
|
||||
has-symbols "^1.0.0"
|
||||
|
||||
is-typedarray@~1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a"
|
||||
@ -1976,11 +2060,21 @@ is-windows@^1.0.2:
|
||||
resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d"
|
||||
integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==
|
||||
|
||||
is-wsl@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d"
|
||||
integrity sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=
|
||||
|
||||
isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
|
||||
integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=
|
||||
|
||||
isexe@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
|
||||
integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=
|
||||
|
||||
isobject@^2.0.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89"
|
||||
@ -2192,6 +2286,15 @@ math-random@^1.0.1:
|
||||
resolved "https://registry.yarnpkg.com/math-random/-/math-random-1.0.4.tgz#5dd6943c938548267016d4e34f057583080c514c"
|
||||
integrity sha512-rUxjysqif/BZQH2yhd5Aaq7vXMSx9NdEsQcyA07uEzIvxgI7zIr33gGsh+RU0/XjmQpCW7RsVof1vlkvQVCK5A==
|
||||
|
||||
md5@^2.2.1:
|
||||
version "2.2.1"
|
||||
resolved "https://registry.yarnpkg.com/md5/-/md5-2.2.1.tgz#53ab38d5fe3c8891ba465329ea23fac0540126f9"
|
||||
integrity sha1-U6s41f48iJG6RlMp6iP6wFQBJvk=
|
||||
dependencies:
|
||||
charenc "~0.0.1"
|
||||
crypt "~0.0.1"
|
||||
is-buffer "~1.1.1"
|
||||
|
||||
media-typer@0.3.0:
|
||||
version "0.3.0"
|
||||
resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
|
||||
@ -2344,7 +2447,7 @@ mute-stream@0.0.7:
|
||||
resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab"
|
||||
integrity sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=
|
||||
|
||||
nan@^2.0.9, nan@^2.8.0, nan@^2.9.2:
|
||||
nan@^2.8.0, nan@^2.9.2:
|
||||
version "2.12.1"
|
||||
resolved "https://registry.yarnpkg.com/nan/-/nan-2.12.1.tgz#7b1aa193e9aa86057e3c7bbd0ac448e770925552"
|
||||
integrity sha512-JY7V6lRkStKcKTvHO5NVSQRv+RV+FIL5pvDoLiAtSL9pKlC5x9PKQcZDsq7m4FO4d57mkhC6Z+QhAh3Jdk5JFw==
|
||||
@ -2406,6 +2509,13 @@ nexe@^2.0.0-rc.34:
|
||||
uglify-es "^3.3.9"
|
||||
uglify-js "3.0.28"
|
||||
|
||||
node-netstat@^1.6.0:
|
||||
version "1.6.0"
|
||||
resolved "https://registry.yarnpkg.com/node-netstat/-/node-netstat-1.6.0.tgz#38c36b5f966b00ffaa2ed6f6321e6ad4487d8c89"
|
||||
integrity sha512-KPDopkvPllhcILoHMWYUxvOO5c+VcPB38LxlOFPiZhZ/hJTMH/GXGCs6nvxu4d6unwsbEfgzJ4pPye3CFv9yTg==
|
||||
dependencies:
|
||||
is-wsl "^1.1.0"
|
||||
|
||||
node-pre-gyp@^0.10.0:
|
||||
version "0.10.3"
|
||||
resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.10.3.tgz#3070040716afdc778747b61b6887bf78880b80fc"
|
||||
@ -2501,6 +2611,11 @@ object-copy@^0.1.0:
|
||||
define-property "^0.2.5"
|
||||
kind-of "^3.0.3"
|
||||
|
||||
object-keys@^1.0.12:
|
||||
version "1.0.12"
|
||||
resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.0.12.tgz#09c53855377575310cca62f55bb334abff7b3ed2"
|
||||
integrity sha512-FTMyFUm2wBcGHnH2eXmz7tC6IwlqQZ6mVZ+6dm6vZ4IQIHjs6FdNsQBuKGPuUUUY6NfJw2PshC08Tn6LzLDOag==
|
||||
|
||||
object-visit@^1.0.0:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb"
|
||||
@ -2576,7 +2691,7 @@ os-homedir@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3"
|
||||
integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M=
|
||||
|
||||
os-tmpdir@^1.0.0, os-tmpdir@~1.0.2:
|
||||
os-tmpdir@^1.0.0, os-tmpdir@^1.0.1, os-tmpdir@~1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
|
||||
integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=
|
||||
@ -2660,6 +2775,16 @@ path-to-regexp@0.1.7:
|
||||
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c"
|
||||
integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=
|
||||
|
||||
pem@^1.14.1:
|
||||
version "1.14.1"
|
||||
resolved "https://registry.yarnpkg.com/pem/-/pem-1.14.1.tgz#8ff3c5884bfcba7bbdfea5b67a7fa24b4ca3bb86"
|
||||
integrity sha512-WY3IzMoh+Gwp4xJTT2MqIOaVzNqU7jHqj7k0pOnLIkNSnOpjhy3PHr9mXGi+C5tRC2z1EX5lvzEbd9BtHumHLQ==
|
||||
dependencies:
|
||||
es6-promisify "^6.0.0"
|
||||
md5 "^2.2.1"
|
||||
os-tmpdir "^1.0.1"
|
||||
which "^1.3.1"
|
||||
|
||||
pend@~1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50"
|
||||
@ -2744,6 +2869,15 @@ process-nextick-args@~2.0.0:
|
||||
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa"
|
||||
integrity sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==
|
||||
|
||||
promise.prototype.finally@^3.1.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/promise.prototype.finally/-/promise.prototype.finally-3.1.0.tgz#66f161b1643636e50e7cf201dc1b84a857f3864e"
|
||||
integrity sha512-7p/K2f6dI+dM8yjRQEGrTQs5hTQixUAdOGpMEA3+pVxpX5oHKRSKAXyLw9Q9HUWDTdwtoo39dSHGQtN90HcEwQ==
|
||||
dependencies:
|
||||
define-properties "^1.1.2"
|
||||
es-abstract "^1.9.0"
|
||||
function-bind "^1.1.1"
|
||||
|
||||
proto-list@~1.2.1:
|
||||
version "1.2.4"
|
||||
resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849"
|
||||
@ -3022,14 +3156,6 @@ seek-bzip@^1.0.5:
|
||||
dependencies:
|
||||
commander "~2.8.1"
|
||||
|
||||
segfault-handler@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/segfault-handler/-/segfault-handler-1.0.1.tgz#9466d8f77d8826cfbdfa811124ece02983fd6ad2"
|
||||
integrity sha512-3koBV3F0IPxTYacnoL7WoFlaMndXsXj62tiVbbW9Kzp3K+F9Y6GWW5XmKSv7j+7nf2M+qjNzc4W1iZoa8vocjw==
|
||||
dependencies:
|
||||
bindings "^1.2.1"
|
||||
nan "^2.0.9"
|
||||
|
||||
semver@^5.3.0, semver@^5.6.0:
|
||||
version "5.6.0"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-5.6.0.tgz#7e74256fbaa49c75aa7c7a205cc22799cac80004"
|
||||
@ -3668,6 +3794,13 @@ watch@^1.0.1:
|
||||
exec-sh "^0.2.0"
|
||||
minimist "^1.2.0"
|
||||
|
||||
which@^1.3.1:
|
||||
version "1.3.1"
|
||||
resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a"
|
||||
integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==
|
||||
dependencies:
|
||||
isexe "^2.0.0"
|
||||
|
||||
wide-align@^1.1.0:
|
||||
version "1.1.3"
|
||||
resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457"
|
||||
|
4
packages/tunnel/package.json
Normal file
4
packages/tunnel/package.json
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"name": "@coder/tunnel",
|
||||
"main": "src/tunnel.ts"
|
||||
}
|
48
packages/tunnel/src/client.ts
Normal file
48
packages/tunnel/src/client.ts
Normal file
@ -0,0 +1,48 @@
|
||||
import { Event, Emitter } from "@coder/events";
|
||||
import { TunnelCloseCode } from "./common";
|
||||
|
||||
export interface TunnelCloseEvent {
|
||||
readonly code: TunnelCloseCode;
|
||||
readonly reason: string;
|
||||
}
|
||||
|
||||
export interface ClientConnection {
|
||||
readonly onData: Event<ArrayBuffer>;
|
||||
readonly onClose: Event<TunnelCloseEvent>;
|
||||
send(data: ArrayBuffer): void;
|
||||
}
|
||||
|
||||
export const forward = (connectionUrl: string): Promise<ClientConnection> => {
|
||||
return new Promise((resolve, reject): void => {
|
||||
const socket = new WebSocket(connectionUrl);
|
||||
const closeEmitter = new Emitter<TunnelCloseEvent>();
|
||||
const dataEmitter = new Emitter<ArrayBuffer>();
|
||||
const connection: ClientConnection = {
|
||||
get onClose(): Event<TunnelCloseEvent> {
|
||||
return closeEmitter.event;
|
||||
},
|
||||
get onData(): Event<ArrayBuffer> {
|
||||
return dataEmitter.event;
|
||||
},
|
||||
send(data: ArrayBuffer): void {
|
||||
socket.send(data);
|
||||
},
|
||||
};
|
||||
socket.binaryType = "arraybuffer";
|
||||
socket.addEventListener("message", (event) => {
|
||||
dataEmitter.emit(event.data);
|
||||
});
|
||||
socket.addEventListener("error", (event) => {
|
||||
reject("uncertain");
|
||||
});
|
||||
socket.addEventListener("open", () => {
|
||||
resolve(connection);
|
||||
});
|
||||
socket.addEventListener("close", (event) => {
|
||||
closeEmitter.emit({
|
||||
code: event.code,
|
||||
reason: event.reason,
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
5
packages/tunnel/src/common.ts
Normal file
5
packages/tunnel/src/common.ts
Normal file
@ -0,0 +1,5 @@
|
||||
export enum TunnelCloseCode {
|
||||
Normal = 1000,
|
||||
Error = 4000,
|
||||
ConnectionRefused = 4001,
|
||||
}
|
53
packages/tunnel/src/server.ts
Normal file
53
packages/tunnel/src/server.ts
Normal file
@ -0,0 +1,53 @@
|
||||
import * as net from "net";
|
||||
import { TunnelCloseCode } from "./common";
|
||||
|
||||
export interface WS {
|
||||
addEventListener(event: "message", cb: (event: {
|
||||
// tslint:disable-next-line:no-any
|
||||
readonly data: any;
|
||||
}) => void): void;
|
||||
addEventListener(event: "close", cb: () => void): void;
|
||||
binaryType: string;
|
||||
close(code: number, reason?: string): void;
|
||||
// tslint:disable-next-line:no-any
|
||||
send(data: any): void;
|
||||
}
|
||||
|
||||
export const handle = async (socket: WS, port: number): Promise<void> => {
|
||||
const hosts = [
|
||||
"127.0.0.1",
|
||||
"::", // localhost
|
||||
];
|
||||
|
||||
let localSocket: net.Socket | undefined;
|
||||
for (let i = 0; i < hosts.length; i++) {
|
||||
if (localSocket) {
|
||||
break;
|
||||
}
|
||||
localSocket = await new Promise((resolve, reject): void => {
|
||||
const socket = net.connect({
|
||||
host: hosts[i],
|
||||
port,
|
||||
}, () => {
|
||||
// Connected
|
||||
resolve(socket);
|
||||
});
|
||||
socket.on("error", (err: Error & { readonly code: string }) => {
|
||||
if (err.code === "ECONNREFUSED") {
|
||||
resolve(undefined);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
if (!localSocket) {
|
||||
socket.close(TunnelCloseCode.ConnectionRefused);
|
||||
|
||||
return;
|
||||
}
|
||||
socket.binaryType = "arraybuffer";
|
||||
socket.addEventListener("message", (event) => localSocket!.write(Buffer.from(event.data)));
|
||||
socket.addEventListener("close", () => localSocket!.end());
|
||||
localSocket.on("data", (data) => socket.send(data));
|
||||
localSocket.on("error", (err) => socket.close(TunnelCloseCode.Error, err.toString()));
|
||||
localSocket.on("close", () => socket.close(TunnelCloseCode.Normal));
|
||||
};
|
@ -2,6 +2,7 @@ import * as paths from "./fill/paths";
|
||||
import "./fill/platform";
|
||||
import "./fill/storageDatabase";
|
||||
import "./fill/windowsService";
|
||||
import "./fill/workspacesService";
|
||||
import "./fill/environmentService";
|
||||
import "./fill/vscodeTextmate";
|
||||
import "./fill/codeEditor";
|
||||
@ -17,13 +18,14 @@ import { LogLevel } from "vs/platform/log/common/log";
|
||||
import { URI } from "vs/base/common/uri";
|
||||
import { INotificationService } from "vs/platform/notification/common/notification";
|
||||
import { IProgressService2, ProgressLocation } from "vs/platform/progress/common/progress";
|
||||
import { ExplorerItem, Model } from "vs/workbench/parts/files/common/explorerModel";
|
||||
import { ExplorerItem, ExplorerModel } from "vs/workbench/parts/files/common/explorerModel";
|
||||
import { DragMouseEvent } from "vs/base/browser/mouseEvent";
|
||||
import { IEditorService, IResourceEditor } from "vs/workbench/services/editor/common/editorService";
|
||||
import { IEditorGroup } from "vs/workbench/services/group/common/editorGroupsService";
|
||||
import { IWindowsService } from "vs/platform/windows/common/windows";
|
||||
import { IWindowsService, IWindowConfiguration } from "vs/platform/windows/common/windows";
|
||||
import { ServiceCollection } from "vs/platform/instantiation/common/serviceCollection";
|
||||
import { RawContextKey, IContextKeyService } from "vs/platform/contextkey/common/contextkey";
|
||||
import { ISingleFolderWorkspaceIdentifier, IWorkspaceIdentifier } from "vs/platform/workspaces/common/workspaces";
|
||||
|
||||
export class Client extends IdeClient {
|
||||
private readonly windowId = parseInt(new Date().toISOString().replace(/[-:.TZ]/g, ""), 10);
|
||||
@ -39,7 +41,7 @@ export class Client extends IdeClient {
|
||||
return this._builtInExtensionsDirectory;
|
||||
}
|
||||
|
||||
public async handleExternalDrop(target: ExplorerItem | Model, originalEvent: DragMouseEvent): Promise<void> {
|
||||
public async handleExternalDrop(target: ExplorerItem | ExplorerModel, originalEvent: DragMouseEvent): Promise<void> {
|
||||
await this.upload.uploadDropped(
|
||||
originalEvent.browserEvent as DragEvent,
|
||||
(target instanceof ExplorerItem ? target : target.roots[0]).resource,
|
||||
@ -93,6 +95,25 @@ export class Client extends IdeClient {
|
||||
return new PasteAction();
|
||||
}
|
||||
|
||||
public set workspace(ws: IWorkspaceIdentifier | ISingleFolderWorkspaceIdentifier | undefined) {
|
||||
if (typeof ws === "undefined") {
|
||||
window.localStorage.removeItem("workspace");
|
||||
} else {
|
||||
window.localStorage.setItem("workspace", JSON.stringify(ws));
|
||||
}
|
||||
|
||||
location.reload();
|
||||
}
|
||||
|
||||
public get workspace(): undefined | IWorkspaceIdentifier | ISingleFolderWorkspaceIdentifier {
|
||||
const ws = window.localStorage.getItem("workspace");
|
||||
try {
|
||||
return JSON.parse(ws!);
|
||||
} catch (ex) {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
public get serviceCollection(): ServiceCollection {
|
||||
if (!this._serviceCollection) {
|
||||
throw new Error("Trying to access service collection before it has been set");
|
||||
@ -162,8 +183,9 @@ export class Client extends IdeClient {
|
||||
this._builtInExtensionsDirectory = data.builtInExtensionsDirectory;
|
||||
process.env.SHELL = data.shell;
|
||||
|
||||
const { startup } = require("./startup");
|
||||
await startup({
|
||||
const workspace = this.workspace || URI.file(data.workingDirectory);
|
||||
const { startup } = require("./startup") as typeof import("vs/workbench/electron-browser/main");
|
||||
const config: IWindowConfiguration = {
|
||||
machineId: "1",
|
||||
windowId: this.windowId,
|
||||
logLevel: LogLevel.Info,
|
||||
@ -174,9 +196,13 @@ export class Client extends IdeClient {
|
||||
nodeCachedDataDir: data.tmpDirectory,
|
||||
perfEntries: [],
|
||||
_: [],
|
||||
folderUri: URI.file(data.workingDirectory),
|
||||
});
|
||||
|
||||
};
|
||||
if ((workspace as IWorkspaceIdentifier).configPath) {
|
||||
config.workspace = workspace as IWorkspaceIdentifier;
|
||||
} else {
|
||||
config.folderUri = workspace as URI;
|
||||
}
|
||||
await startup(config);
|
||||
const contextKeys = this.serviceCollection.get(IContextKeyService) as IContextKeyService;
|
||||
const bounded = this.clipboardContextKey.bindTo(contextKeys);
|
||||
this.clipboard.onPermissionChange((enabled) => {
|
||||
|
146
packages/vscode/src/dialog.scss
Normal file
146
packages/vscode/src/dialog.scss
Normal file
@ -0,0 +1,146 @@
|
||||
.dialog {
|
||||
--primary: #2A2E37;
|
||||
--border: black;
|
||||
--faded: #a0a1a5;
|
||||
--header-background: #161616;
|
||||
--header-foreground: white;
|
||||
--list-active-selection-background: rgb(0, 120, 160);
|
||||
--list-active-selection-foreground: white;
|
||||
--list-hover-background: rgb(36, 39, 46);
|
||||
font-family: inherit;
|
||||
box-shadow: 0 18px 80px 10px rgba(0, 0, 0, 0.1);
|
||||
background-color: var(--primary);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
user-select: none;
|
||||
overflow: hidden;
|
||||
border-radius: 5px;
|
||||
|
||||
.monaco-tl-twistie {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.title {
|
||||
background-color: var(--header-background);
|
||||
color: var(--header-foreground);
|
||||
padding: 1px;
|
||||
font-size: 11px;
|
||||
font-weight: normal;
|
||||
text-transform: uppercase;
|
||||
white-space: nowrap;
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
.nav {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
padding: 4px;
|
||||
padding-top: 8px;
|
||||
padding-bottom: 8px;
|
||||
border-bottom: 1px solid var(--border);
|
||||
min-height: 32px;
|
||||
}
|
||||
|
||||
.path {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
|
||||
.path-part {
|
||||
padding: 5px;
|
||||
border-radius: 3px;
|
||||
font-size: 1.2em;
|
||||
cursor: pointer;
|
||||
|
||||
&:not(:first-child) {
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
&.active {
|
||||
font-weight: bold;
|
||||
color: var(--list-active-selection-foreground);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.file-area {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.dialog-grid {
|
||||
display: grid;
|
||||
grid-template-columns: 2fr 0.2fr 0.8fr;
|
||||
}
|
||||
|
||||
.headings {
|
||||
padding: 8px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.dialog-entry {
|
||||
cursor: pointer;
|
||||
font-size: 1.2em;
|
||||
padding: 0px;
|
||||
padding-left: 8px;
|
||||
padding-right: 8px;
|
||||
|
||||
.dialog-entry-info {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.dialog-entry-icon {
|
||||
width: 16px;
|
||||
height: 19px;
|
||||
display: inline-block;
|
||||
margin-right: 5px;
|
||||
margin-bottom: -3px;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: var(--list-hover-background);
|
||||
}
|
||||
|
||||
&.active {
|
||||
background-color: var(--list-active-selection-background);
|
||||
color: var(--list-active-selection-foreground);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.buttons {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
padding: 10px;
|
||||
position: relative;
|
||||
background: var(--primary);
|
||||
border-top: 1px solid var(--border);
|
||||
|
||||
button:first-child {
|
||||
margin-left: auto;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
button {
|
||||
background: transparent;
|
||||
outline: none;
|
||||
border: 0;
|
||||
color: var(--faded);
|
||||
padding: 10px;
|
||||
padding-left: 18px;
|
||||
padding-right: 18px;
|
||||
transition: 150ms background ease, 150ms color ease;
|
||||
cursor: pointer;
|
||||
border-radius: 5px;
|
||||
|
||||
&:hover {
|
||||
background: var(--titlebar);
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.monaco-shell .monaco-tree.focused.no-focused-item:focus:before, .monaco-shell .monaco-list:not(.element-focused):focus:before {
|
||||
display: none;
|
||||
}
|
471
packages/vscode/src/dialog.ts
Normal file
471
packages/vscode/src/dialog.ts
Normal file
@ -0,0 +1,471 @@
|
||||
import { Emitter, Event } from "@coder/events";
|
||||
import { client as ideClient } from "@coder/ide/src/fill/client";
|
||||
import { client } from "@coder/vscode/src/client";
|
||||
import * as fs from "fs";
|
||||
import * as path from "path";
|
||||
import { $, addClass, append } from "vs/base/browser/dom";
|
||||
import { HighlightedLabel } from "vs/base/browser/ui/highlightedlabel/highlightedLabel";
|
||||
import { ObjectTree } from "vs/base/browser/ui/tree/objectTree";
|
||||
import { ITreeElement, ITreeNode, ITreeRenderer, TreeFilterResult, TreeVisibility } from "vs/base/browser/ui/tree/tree";
|
||||
import { KeyCode } from "vs/base/common/keyCodes";
|
||||
import { URI } from "vs/base/common/uri";
|
||||
import { getIconClasses } from "vs/editor/common/services/getIconClasses";
|
||||
import { IModelService } from "vs/editor/common/services/modelService";
|
||||
import { IModeService } from "vs/editor/common/services/modeService";
|
||||
import { FileKind } from "vs/platform/files/common/files";
|
||||
import "./dialog.scss";
|
||||
import { IThemeService } from "vs/platform/theme/common/themeService";
|
||||
|
||||
declare var __non_webpack_require__: typeof require;
|
||||
|
||||
export enum DialogType {
|
||||
NewFolder,
|
||||
Save,
|
||||
Open,
|
||||
}
|
||||
|
||||
export interface CommonDialogOptions {
|
||||
readonly title?: string;
|
||||
readonly defaultPath?: string;
|
||||
readonly buttonLabel?: string;
|
||||
}
|
||||
|
||||
export interface OpenDialogOptions extends CommonDialogOptions {
|
||||
readonly properties: {
|
||||
readonly openFile: true;
|
||||
readonly openDirectory?: boolean;
|
||||
readonly showHiddenFiles?: boolean;
|
||||
} | {
|
||||
readonly openDirectory: true;
|
||||
readonly showHiddenFiles?: boolean;
|
||||
readonly openFile?: boolean;
|
||||
};
|
||||
}
|
||||
|
||||
export interface SaveDialogOptions extends CommonDialogOptions {
|
||||
readonly type: DialogType.Save;
|
||||
readonly nameFieldLabel?: string;
|
||||
}
|
||||
|
||||
export type DialogOptions = OpenDialogOptions | SaveDialogOptions;
|
||||
|
||||
export const showOpenDialog = (options: OpenDialogOptions): Promise<string> => {
|
||||
return new Promise<string>((resolve, reject): void => {
|
||||
const dialog = new Dialog(DialogType.Open, options);
|
||||
dialog.onSelect((e) => {
|
||||
dialog.dispose();
|
||||
resolve(e);
|
||||
});
|
||||
dialog.onError((e) => {
|
||||
dialog.dispose();
|
||||
reject(e);
|
||||
});
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
interface DialogEntry {
|
||||
readonly fullPath: string;
|
||||
readonly name: string;
|
||||
readonly isDirectory: boolean;
|
||||
readonly size: number;
|
||||
readonly lastModified: string;
|
||||
}
|
||||
|
||||
class Dialog {
|
||||
private _path: string | undefined;
|
||||
|
||||
private static readonly UpperDirId = "..";
|
||||
|
||||
private readonly filesNode: HTMLElement;
|
||||
private readonly pathNode: HTMLElement;
|
||||
|
||||
private readonly entryList: ObjectTree<DialogEntry, string>;
|
||||
private readonly background: HTMLElement;
|
||||
private readonly root: HTMLElement;
|
||||
|
||||
private readonly selectEmitter: Emitter<string>;
|
||||
private readonly errorEmitter: Emitter<Error>;
|
||||
|
||||
public constructor(
|
||||
private readonly type: DialogType,
|
||||
private readonly options: DialogOptions,
|
||||
) {
|
||||
this.selectEmitter = new Emitter();
|
||||
this.errorEmitter = new Emitter();
|
||||
|
||||
this.background = document.createElement("div");
|
||||
this.background.style.position = "absolute";
|
||||
this.background.style.top = "0";
|
||||
this.background.style.left = "0";
|
||||
this.background.style.bottom = "0";
|
||||
this.background.style.right = "0";
|
||||
this.background.style.zIndex = "5";
|
||||
this.background.style.display = "flex";
|
||||
this.background.style.alignItems = "center";
|
||||
this.background.style.justifyContent = "center";
|
||||
this.background.style.background = "rgba(0, 0, 0, 0.25)";
|
||||
|
||||
this.root = document.createElement("div");
|
||||
this.root.style.width = "850px";
|
||||
this.root.style.height = "600px";
|
||||
this.background.appendChild(this.root);
|
||||
document.body.appendChild(this.background);
|
||||
this.root.classList.add("dialog");
|
||||
|
||||
const setProperty = (vari: string, id: string): void => {
|
||||
const getColor = (id: string): string | undefined => {
|
||||
const ts = client.serviceCollection.get<IThemeService>(IThemeService) as IThemeService;
|
||||
const c = ts.getTheme().getColor(id);
|
||||
if (!c) {
|
||||
return;
|
||||
}
|
||||
|
||||
return c.toString();
|
||||
};
|
||||
const c = getColor(id);
|
||||
if (c) {
|
||||
this.root.style.setProperty(vari, c);
|
||||
}
|
||||
};
|
||||
setProperty("--primary", "sideBar.background");
|
||||
setProperty("--list-active-selection-background", "list.activeSelectionBackground");
|
||||
setProperty("--list-active-selection-foreground", "list.activeSelectionForeground");
|
||||
setProperty("--list-hover-background", "list.hoverBackground");
|
||||
setProperty("--header-background", "sideBarSectionHeader.background");
|
||||
setProperty("--header-foreground", "sideBarSectionHeader.foreground");
|
||||
setProperty("--border", "panel.border");
|
||||
|
||||
this.background.addEventListener("contextmenu", (event) => {
|
||||
event.preventDefault();
|
||||
});
|
||||
|
||||
const titleNode = document.createElement("div");
|
||||
titleNode.classList.add("title");
|
||||
let title: string | undefined;
|
||||
switch (this.type) {
|
||||
// case DialogType.NewFolder:
|
||||
// title = "New Folder";
|
||||
// break;
|
||||
case DialogType.Open:
|
||||
title = "Open File";
|
||||
break;
|
||||
case DialogType.Save:
|
||||
title = "Save File";
|
||||
break;
|
||||
default:
|
||||
throw new Error("Uncased type");
|
||||
}
|
||||
titleNode.innerText = options.title || title;
|
||||
this.root.appendChild(titleNode);
|
||||
|
||||
const navItems = document.createElement("div");
|
||||
navItems.classList.add("nav");
|
||||
|
||||
this.pathNode = document.createElement("div");
|
||||
this.pathNode.classList.add("path");
|
||||
navItems.appendChild(this.pathNode);
|
||||
this.root.appendChild(navItems);
|
||||
|
||||
const fileAreaNode = document.createElement("div");
|
||||
fileAreaNode.classList.add("file-area");
|
||||
fileAreaNode.classList.add("show-file-icons");
|
||||
|
||||
const headingsNode = document.createElement("div");
|
||||
headingsNode.className = "headings dialog-grid";
|
||||
["Name", "Size", "Last Modified"].forEach(e => {
|
||||
const header = document.createElement("div");
|
||||
header.innerText = e;
|
||||
headingsNode.appendChild(header);
|
||||
});
|
||||
|
||||
this.filesNode = document.createElement("div");
|
||||
this.filesNode.className = "files-list";
|
||||
fileAreaNode.appendChild(headingsNode);
|
||||
this.entryList = new ObjectTree<DialogEntry, string>(this.filesNode, {
|
||||
getHeight: (entry: DialogEntry): number => {
|
||||
return 20;
|
||||
},
|
||||
getTemplateId: (entry: DialogEntry): string => {
|
||||
return "dialog-entry";
|
||||
},
|
||||
}, [new DialogEntryRenderer()], {
|
||||
openController: {
|
||||
shouldOpen: (event): boolean => {
|
||||
return true;
|
||||
},
|
||||
},
|
||||
keyboardNavigationLabelProvider: {
|
||||
getKeyboardNavigationLabel: (element): string => {
|
||||
return element.name;
|
||||
},
|
||||
mightProducePrintableCharacter: (event): boolean => {
|
||||
if (event.ctrlKey || event.metaKey) {
|
||||
// ignore ctrl/cmd-combination but not shift/alt-combinatios
|
||||
return false;
|
||||
}
|
||||
// weak check for certain ranges. this is properly implemented in a subclass
|
||||
// with access to the KeyboardMapperFactory.
|
||||
if ((event.keyCode >= KeyCode.KEY_A && event.keyCode <= KeyCode.KEY_Z)
|
||||
|| (event.keyCode >= KeyCode.KEY_0 && event.keyCode <= KeyCode.KEY_9)
|
||||
|| event.keyCode === KeyCode.US_DOT || event.keyCode === KeyCode.US_SLASH || event.keyCode === KeyCode.US_MINUS) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
},
|
||||
automaticKeyboardNavigation: true,
|
||||
enableKeyboardNavigation: true,
|
||||
multipleSelectionSupport: false,
|
||||
openOnSingleClick: false,
|
||||
filter: {
|
||||
filter: (): TreeFilterResult<string> => {
|
||||
// tslint:disable-next-line:no-any
|
||||
(<any>this.entryList)._options.simpleKeyboardNavigation = true;
|
||||
// tslint:disable-next-line:no-any
|
||||
const pat = (<any>this.entryList).typeFilterController.filter._pattern;
|
||||
|
||||
return {
|
||||
data: pat,
|
||||
visibility: TreeVisibility.Visible,
|
||||
};
|
||||
},
|
||||
},
|
||||
filterOnType: true,
|
||||
});
|
||||
// tslint:disable-next-line:no-any
|
||||
(<any>this.entryList).focusNavigationFilter = (node: ITreeNode<DialogEntry, string>): boolean => {
|
||||
if (node.filterData) {
|
||||
return node.element.name.toLowerCase().startsWith(node.filterData.toLowerCase()!);
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
this.entryList.onDidOpen((event) => {
|
||||
const element = event.elements[0]!;
|
||||
if (!element) {
|
||||
const fv = this.filterValue;
|
||||
|
||||
if (fv === Dialog.UpperDirId) {
|
||||
this.path = path.dirname(this._path!);
|
||||
}
|
||||
|
||||
if (fv.startsWith("/")) {
|
||||
fs.stat(fv, (err, stats) => {
|
||||
if (err) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (stats.isDirectory()) {
|
||||
this.path = fv;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
if (element.isDirectory) {
|
||||
this.path = element.fullPath;
|
||||
} else {
|
||||
// Open
|
||||
this.selectEmitter.emit(element.fullPath);
|
||||
}
|
||||
});
|
||||
fileAreaNode.appendChild(this.entryList.getHTMLElement());
|
||||
this.root.appendChild(fileAreaNode);
|
||||
|
||||
const buttonsNode = document.createElement("div");
|
||||
buttonsNode.className = "buttons";
|
||||
const cancelBtn = document.createElement("button");
|
||||
cancelBtn.innerText = "Cancel";
|
||||
cancelBtn.addEventListener("click", () => {
|
||||
this.errorEmitter.emit(new Error("Cancelled"));
|
||||
});
|
||||
buttonsNode.appendChild(cancelBtn);
|
||||
const confirmBtn = document.createElement("button");
|
||||
confirmBtn.innerText = "Confirm";
|
||||
confirmBtn.addEventListener("click", () => {
|
||||
if (this._path) {
|
||||
this.selectEmitter.emit(this._path);
|
||||
}
|
||||
});
|
||||
buttonsNode.appendChild(confirmBtn);
|
||||
this.root.appendChild(buttonsNode);
|
||||
this.entryList.layout();
|
||||
|
||||
this.path = options.defaultPath || "/";
|
||||
}
|
||||
|
||||
public get onSelect(): Event<string> {
|
||||
return this.selectEmitter.event;
|
||||
}
|
||||
|
||||
public get onError(): Event<Error> {
|
||||
return this.errorEmitter.event;
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
this.selectEmitter.dispose();
|
||||
this.errorEmitter.dispose();
|
||||
this.entryList.dispose();
|
||||
this.background.remove();
|
||||
}
|
||||
|
||||
private buildPath(): void {
|
||||
while (this.pathNode.lastChild) {
|
||||
this.pathNode.removeChild(this.pathNode.lastChild);
|
||||
}
|
||||
|
||||
if (!this._path) {
|
||||
throw new Error("cannot build path node without valid path");
|
||||
}
|
||||
|
||||
const pathParts = ["", ...this._path.split("/").filter((p) => p.length > 0)];
|
||||
|
||||
for (let i = 0; i < pathParts.length; i++) {
|
||||
const pathPartNode = document.createElement("div");
|
||||
pathPartNode.classList.add("path-part");
|
||||
pathPartNode.innerText = pathParts[i].length > 0 ? pathParts[i] : "/";
|
||||
|
||||
if (i === pathParts.length - 1) {
|
||||
pathPartNode.classList.add("active");
|
||||
}
|
||||
|
||||
pathPartNode.addEventListener("click", () => {
|
||||
this.path = "/" + pathParts.slice(0, i + 1).join("/");
|
||||
});
|
||||
|
||||
this.pathNode.appendChild(pathPartNode);
|
||||
}
|
||||
}
|
||||
|
||||
private set path(directory: string) {
|
||||
const ts = Date.now();
|
||||
this.list(directory).then((value) => {
|
||||
this._path = directory;
|
||||
this.buildPath();
|
||||
|
||||
while (this.filesNode.lastChild) {
|
||||
this.filesNode.removeChild(this.filesNode.lastChild);
|
||||
}
|
||||
|
||||
const items = value.filter((v) => {
|
||||
if (v.name.startsWith(".")) {
|
||||
const props = (this.options as OpenDialogOptions).properties;
|
||||
if (props && props.showHiddenFiles) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
this.entryList.setChildren(null, items.map((i: DialogEntry): ITreeElement<DialogEntry> => ({ element: i })));
|
||||
this.entryList.domFocus();
|
||||
this.entryList.setFocus([null]);
|
||||
// Clears the input on refresh
|
||||
// tslint:disable-next-line:no-any
|
||||
(<any>this.entryList).typeFilterController.onInput("");
|
||||
}).catch((ex) => {
|
||||
this.errorEmitter.emit(ex);
|
||||
});
|
||||
}
|
||||
|
||||
private get filterValue(): string {
|
||||
// tslint:disable-next-line:no-any
|
||||
return (<any>this.entryList).typeFilterController.filter._pattern;
|
||||
}
|
||||
|
||||
private async list(directory: string): Promise<ReadonlyArray<DialogEntry>> {
|
||||
return ideClient.evaluate((directory) => {
|
||||
const fs = __non_webpack_require__("fs") as typeof import("fs");
|
||||
const util = __non_webpack_require__("util") as typeof import("util");
|
||||
const path = __non_webpack_require__("path") as typeof import("path");
|
||||
|
||||
return util.promisify(fs.readdir)(directory).then((paths) => {
|
||||
paths = paths.sort();
|
||||
|
||||
return Promise.all(paths.map(p => util.promisify(fs.stat)(path.join(directory, p)))).then((stats) => {
|
||||
return {
|
||||
paths,
|
||||
stats,
|
||||
};
|
||||
});
|
||||
}).then(({ paths, stats }) => {
|
||||
return stats.map((stat, index): DialogEntry => {
|
||||
return {
|
||||
fullPath: path.join(directory, paths[index]),
|
||||
name: paths[index],
|
||||
isDirectory: stat.isDirectory(),
|
||||
lastModified: stat.mtime.toDateString(),
|
||||
size: stat.size,
|
||||
};
|
||||
});
|
||||
});
|
||||
}, directory);
|
||||
}
|
||||
}
|
||||
|
||||
interface DialogEntryData {
|
||||
icon: HTMLElement;
|
||||
size: HTMLElement;
|
||||
lastModified: HTMLElement;
|
||||
label: HighlightedLabel;
|
||||
}
|
||||
|
||||
class DialogEntryRenderer implements ITreeRenderer<DialogEntry, string, DialogEntryData> {
|
||||
public get templateId(): string {
|
||||
return "dialog-entry";
|
||||
}
|
||||
|
||||
public renderTemplate(container: HTMLElement): DialogEntryData {
|
||||
addClass(container, "dialog-entry");
|
||||
addClass(container, "dialog-grid");
|
||||
|
||||
const wrapper = append(container, $(".dialog-entry-info"));
|
||||
const icon: HTMLElement = append(wrapper, $("div"));
|
||||
const name = append(wrapper, $(".dialog-entry-name"));
|
||||
const label = new HighlightedLabel(name, false);
|
||||
append(container, wrapper);
|
||||
const size = append(container, $(".dialog-entry-size"));
|
||||
const mtime = append(container, $(".dialog-entry-mtime"));
|
||||
|
||||
return {
|
||||
icon,
|
||||
size,
|
||||
lastModified: mtime,
|
||||
label,
|
||||
};
|
||||
}
|
||||
|
||||
public renderElement(node: ITreeNode<DialogEntry, string>, index: number, templateData: DialogEntryData): void {
|
||||
templateData.icon.className = "dialog-entry-icon monaco-icon-label";
|
||||
const classes = getIconClasses(
|
||||
client.serviceCollection.get<IModelService>(IModelService) as IModelService,
|
||||
client.serviceCollection.get<IModeService>(IModeService) as IModeService,
|
||||
URI.file(node.element.name),
|
||||
node.element.isDirectory ? FileKind.FOLDER : FileKind.FILE,
|
||||
);
|
||||
templateData.icon.hidden = classes.length === 0;
|
||||
classes.forEach((c) => {
|
||||
try {
|
||||
templateData.icon.classList.add(c);
|
||||
} catch (ex) {
|
||||
// Nothin needed. Sometimes bad classes are given
|
||||
}
|
||||
});
|
||||
templateData.label.set(node.element.name, typeof node.filterData === "string" && node.element.name.toLowerCase().startsWith(node.filterData.toLowerCase()) ? [{
|
||||
start: 0,
|
||||
end: node.filterData.length,
|
||||
}] : []);
|
||||
templateData.size.innerText = node.element.size.toString();
|
||||
templateData.lastModified.innerText = node.element.lastModified;
|
||||
}
|
||||
|
||||
public disposeTemplate(templateData: DialogEntryData): void {
|
||||
// throw new Error("Method not implemented.");
|
||||
}
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
import { logger } from "@coder/logger";
|
||||
import { IDisposable } from "vs/base/common/lifecycle";
|
||||
import * as actions from "vs/platform/actions/common/actions";
|
||||
import { ToggleDevToolsAction } from "vs/workbench/electron-browser/actions";
|
||||
import { ToggleDevToolsAction } from "vs/workbench/electron-browser/actions/developerActions";
|
||||
|
||||
// Intercept appending menu items so we can skip items that won't work.
|
||||
const originalAppend = actions.MenuRegistry.appendMenuItem.bind(actions.MenuRegistry);
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { readFile, writeFile } from "fs";
|
||||
import { readFile, writeFile, mkdir } from "fs";
|
||||
import * as path from "path";
|
||||
import { promisify } from "util";
|
||||
import { IDisposable } from "@coder/disposable";
|
||||
@ -7,6 +7,8 @@ import * as workspaceStorage from "vs/base/node/storage";
|
||||
import * as globalStorage from "vs/platform/storage/node/storageIpc";
|
||||
import * as paths from "./paths";
|
||||
import { logger, field } from "@coder/logger";
|
||||
import { client } from "@coder/vscode/src/client";
|
||||
import { IStorageService, WillSaveStateReason } from "vs/platform/storage/common/storage";
|
||||
|
||||
class StorageDatabase implements workspaceStorage.IStorageDatabase {
|
||||
public readonly onDidChangeItemsExternal = Event.None;
|
||||
@ -20,11 +22,9 @@ class StorageDatabase implements workspaceStorage.IStorageDatabase {
|
||||
if (!navigator.sendBeacon) {
|
||||
throw new Error("cannot save state");
|
||||
}
|
||||
// TODO: Need to use navigator.sendBeacon instead of the web socket, or we
|
||||
// need to save when there is a change. Should we save as a sqlite3
|
||||
// database instead of JSON? Could send to the server the way the global
|
||||
// storage works. Or maybe fill `vscode-sqlite3` to do that.
|
||||
this.save();
|
||||
|
||||
this.triggerFlush(WillSaveStateReason.SHUTDOWN);
|
||||
navigator.sendBeacon(`/resource${this.path}`, this.content);
|
||||
});
|
||||
}
|
||||
|
||||
@ -58,7 +58,7 @@ class StorageDatabase implements workspaceStorage.IStorageDatabase {
|
||||
request.delete.forEach(key => this.items.delete(key));
|
||||
}
|
||||
|
||||
return Promise.resolve();
|
||||
return this.save();
|
||||
}
|
||||
|
||||
public close(): Promise<void> {
|
||||
@ -69,13 +69,38 @@ class StorageDatabase implements workspaceStorage.IStorageDatabase {
|
||||
return Promise.resolve("ok");
|
||||
}
|
||||
|
||||
private save(): Promise<void> {
|
||||
private async save(): Promise<void> {
|
||||
try {
|
||||
await promisify(mkdir)(path.dirname(this.path));
|
||||
} catch (ex) {}
|
||||
|
||||
return promisify(writeFile)(this.path, this.content);
|
||||
}
|
||||
|
||||
private triggerFlush(reason: WillSaveStateReason = WillSaveStateReason.NONE): boolean {
|
||||
// tslint:disable-next-line:no-any
|
||||
const storageService = client.serviceCollection.get<IStorageService>(IStorageService) as any;
|
||||
if (reason === WillSaveStateReason.SHUTDOWN && storageService.close) {
|
||||
storageService.close();
|
||||
|
||||
return true;
|
||||
}
|
||||
if (storageService._onWillSaveState) {
|
||||
storageService._onWillSaveState.fire({ reason });
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private get content(): string {
|
||||
const json: { [key: string]: string } = {};
|
||||
this.items.forEach((value, key) => {
|
||||
json[key] = value;
|
||||
});
|
||||
|
||||
return promisify(writeFile)(this.path, JSON.stringify(json));
|
||||
return JSON.stringify(json);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,13 +1,14 @@
|
||||
import * as electron from "electron";
|
||||
import { Emitter } from "@coder/events";
|
||||
import * as windowsIpc from "vs/platform/windows/node/windowsIpc";
|
||||
import { IWindowsService, INativeOpenDialogOptions, MessageBoxOptions, SaveDialogOptions, OpenDialogOptions, IMessageBoxResult, IDevToolsOptions, IEnterWorkspaceResult, CrashReporterStartOptions, INewWindowOptions } from "vs/platform/windows/common/windows";
|
||||
import { IWindowsService, INativeOpenDialogOptions, MessageBoxOptions, SaveDialogOptions, OpenDialogOptions, IMessageBoxResult, IDevToolsOptions, IEnterWorkspaceResult, CrashReporterStartOptions, INewWindowOptions, IOpenFileRequest, IAddFoldersRequest } from "vs/platform/windows/common/windows";
|
||||
import { ParsedArgs } from "vs/platform/environment/common/environment";
|
||||
import { IWorkspaceIdentifier, IWorkspaceFolderCreationData, ISingleFolderWorkspaceIdentifier } from "vs/platform/workspaces/common/workspaces";
|
||||
import { URI } from "vs/base/common/uri";
|
||||
import { IRecentlyOpened } from "vs/platform/history/common/history";
|
||||
import { ISerializableCommandAction } from "vs/platform/actions/common/actions";
|
||||
import { client } from "../client";
|
||||
import { showOpenDialog } from "../dialog";
|
||||
|
||||
/**
|
||||
* Instead of going to the shared process, we'll directly run these methods on
|
||||
@ -34,20 +35,70 @@ class WindowsService implements IWindowsService {
|
||||
private readonly window = new electron.BrowserWindow();
|
||||
|
||||
// Dialogs
|
||||
public pickFileFolderAndOpen(_options: INativeOpenDialogOptions): Promise<void> {
|
||||
throw new Error("not implemented");
|
||||
public async pickFileFolderAndOpen(_options: INativeOpenDialogOptions): Promise<void> {
|
||||
showOpenDialog({
|
||||
...(_options.dialogOptions || {}),
|
||||
properties: {
|
||||
openFile: true,
|
||||
openDirectory: true,
|
||||
},
|
||||
}).then((path) => {
|
||||
// tslint:disable-next-line:no-any
|
||||
(<any>electron.ipcMain).send("vscode:openFiles", {
|
||||
filesToOpen: [{
|
||||
fileUri: URI.file(path),
|
||||
}],
|
||||
} as IOpenFileRequest);
|
||||
}).catch((ex) => {
|
||||
//
|
||||
});
|
||||
}
|
||||
|
||||
public pickFileAndOpen(_options: INativeOpenDialogOptions): Promise<void> {
|
||||
throw new Error("not implemented");
|
||||
public async pickFileAndOpen(_options: INativeOpenDialogOptions): Promise<void> {
|
||||
showOpenDialog({
|
||||
...(_options.dialogOptions || {}),
|
||||
properties: {
|
||||
openFile: true,
|
||||
},
|
||||
}).then((path) => {
|
||||
// tslint:disable-next-line:no-any
|
||||
(<any>electron.ipcMain).send("vscode:openFiles", {
|
||||
filesToOpen: [{
|
||||
fileUri: URI.file(path),
|
||||
}],
|
||||
} as IOpenFileRequest);
|
||||
}).catch((ex) => {
|
||||
//
|
||||
});
|
||||
}
|
||||
|
||||
public pickFolderAndOpen(_options: INativeOpenDialogOptions): Promise<void> {
|
||||
throw new Error("not implemented");
|
||||
public async pickFolderAndOpen(_options: INativeOpenDialogOptions): Promise<void> {
|
||||
showOpenDialog({
|
||||
...(_options.dialogOptions || {}),
|
||||
properties: {
|
||||
openDirectory: true,
|
||||
},
|
||||
}).then((path) => {
|
||||
client.workspace = URI.file(path);
|
||||
}).catch((ex) => {
|
||||
//
|
||||
});
|
||||
}
|
||||
|
||||
public pickWorkspaceAndOpen(_options: INativeOpenDialogOptions): Promise<void> {
|
||||
throw new Error("not implemented");
|
||||
public async pickWorkspaceAndOpen(_options: INativeOpenDialogOptions): Promise<void> {
|
||||
showOpenDialog({
|
||||
...(_options.dialogOptions || {}),
|
||||
properties: {
|
||||
openDirectory: true,
|
||||
},
|
||||
}).then((path) => {
|
||||
// tslint:disable-next-line:no-any
|
||||
(<any>electron.ipcMain).send("vscode:addFolders", {
|
||||
foldersToAdd: [URI.file(path)],
|
||||
} as IAddFoldersRequest);
|
||||
}).catch((ex) => {
|
||||
//
|
||||
});
|
||||
}
|
||||
|
||||
public showMessageBox(windowId: number, options: MessageBoxOptions): Promise<IMessageBoxResult> {
|
||||
@ -70,10 +121,14 @@ class WindowsService implements IWindowsService {
|
||||
}
|
||||
|
||||
public showOpenDialog(windowId: number, options: OpenDialogOptions): Promise<string[]> {
|
||||
return new Promise((resolve): void => {
|
||||
electron.dialog.showOpenDialog(this.getWindowById(windowId), options, (filePaths, _bookmarks) => {
|
||||
resolve(filePaths);
|
||||
});
|
||||
return showOpenDialog({
|
||||
...(options || {}),
|
||||
properties: {
|
||||
openDirectory: true,
|
||||
openFile: true,
|
||||
},
|
||||
}).then((path) => {
|
||||
return [path];
|
||||
});
|
||||
}
|
||||
|
||||
@ -93,8 +148,17 @@ class WindowsService implements IWindowsService {
|
||||
throw new Error("not implemented");
|
||||
}
|
||||
|
||||
public enterWorkspace(_windowId: number, _path: string): Promise<IEnterWorkspaceResult> {
|
||||
throw new Error("not implemented");
|
||||
public enterWorkspace(_windowId: number, _path: URI): Promise<IEnterWorkspaceResult> {
|
||||
if (_path.path.endsWith(".json")) {
|
||||
client.workspace = {
|
||||
id: "Untitled",
|
||||
configPath: _path.path,
|
||||
};
|
||||
} else {
|
||||
client.workspace = _path;
|
||||
}
|
||||
|
||||
return undefined!;
|
||||
}
|
||||
|
||||
public createAndEnterWorkspace(_windowId: number, _folders?: IWorkspaceFolderCreationData[], _path?: string): Promise<IEnterWorkspaceResult> {
|
||||
@ -251,8 +315,8 @@ class WindowsService implements IWindowsService {
|
||||
return Promise.resolve(1);
|
||||
}
|
||||
|
||||
public openExternal(_url: string): Promise<boolean> {
|
||||
throw new Error("not implemented");
|
||||
public async openExternal(_url: string): Promise<boolean> {
|
||||
return typeof window.open(_url, "_blank") !== "undefined";
|
||||
}
|
||||
|
||||
public startCrashReporter(_config: CrashReporterStartOptions): Promise<void> {
|
||||
|
@ -4,7 +4,7 @@ import { Registry } from "vs/platform/registry/common/platform";
|
||||
import { IWorkbenchActionRegistry, Extensions } from "vs/workbench/common/actions";
|
||||
import { SyncActionDescriptor } from "vs/platform/actions/common/actions";
|
||||
import { ContextKeyExpr } from "vs/platform/contextkey/common/contextkey";
|
||||
import { ToggleDevToolsAction } from "vs/workbench/electron-browser/actions";
|
||||
import { ToggleDevToolsAction } from "vs/workbench/electron-browser/actions/developerActions";
|
||||
import { TerminalPasteAction } from "vs/workbench/parts/terminal/electron-browser/terminalActions";
|
||||
import { KEYBINDING_CONTEXT_TERMINAL_FOCUS } from "vs/workbench/parts/terminal/common/terminal";
|
||||
import { KeyCode, KeyMod } from "vs/base/common/keyCodes";
|
||||
|
40
packages/vscode/src/fill/workspacesService.ts
Normal file
40
packages/vscode/src/fill/workspacesService.ts
Normal file
@ -0,0 +1,40 @@
|
||||
import { URI } from "vs/base/common/uri";
|
||||
import { IEnvironmentService } from "vs/platform/environment/common/environment";
|
||||
import { ILogService } from "vs/platform/log/common/log";
|
||||
import { IWorkspaceFolderCreationData, IWorkspaceIdentifier, IWorkspacesService } from "vs/platform/workspaces/common/workspaces";
|
||||
import { WorkspacesMainService } from "vs/platform/workspaces/electron-main/workspacesMainService";
|
||||
import * as workspacesIpc from "vs/platform/workspaces/node/workspacesIpc";
|
||||
import { client } from "../client";
|
||||
|
||||
/**
|
||||
* Instead of going to the shared process, we'll directly run these methods on
|
||||
* the client. This setup means we can only control the current window.
|
||||
*/
|
||||
class WorkspacesService implements IWorkspacesService {
|
||||
// tslint:disable-next-line:no-any
|
||||
public _serviceBrand: any;
|
||||
|
||||
public createUntitledWorkspace(folders?: IWorkspaceFolderCreationData[] | undefined): Promise<IWorkspaceIdentifier> {
|
||||
const mainService = new WorkspacesMainService(
|
||||
client.serviceCollection.get<IEnvironmentService>(IEnvironmentService) as IEnvironmentService,
|
||||
client.serviceCollection.get<ILogService>(ILogService) as ILogService,
|
||||
);
|
||||
|
||||
// lib/vscode/src/vs/platform/workspaces/node/workspacesIpc.ts
|
||||
const rawFolders: IWorkspaceFolderCreationData[] = folders!;
|
||||
if (Array.isArray(rawFolders)) {
|
||||
folders = rawFolders.map(rawFolder => {
|
||||
return {
|
||||
uri: URI.revive(rawFolder.uri), // convert raw URI back to real URI
|
||||
name: rawFolder.name!,
|
||||
} as IWorkspaceFolderCreationData;
|
||||
});
|
||||
}
|
||||
|
||||
return mainService.createUntitledWorkspace(folders);
|
||||
}
|
||||
}
|
||||
|
||||
const target = workspacesIpc as typeof workspacesIpc;
|
||||
// @ts-ignore TODO: don't ignore it.
|
||||
target.WorkspacesChannelClient = WorkspacesService;
|
@ -5,144 +5,176 @@
|
||||
|
||||
import "vs/loader";
|
||||
|
||||
// Base
|
||||
import "vs/base/common/strings";
|
||||
import "vs/base/common/errors";
|
||||
//#region --- workbench/editor core
|
||||
|
||||
// Configuration
|
||||
import "vs/workbench/services/configuration/common/configurationExtensionPoint";
|
||||
|
||||
// Editor
|
||||
import "vs/editor/editor.all";
|
||||
|
||||
// Platform
|
||||
import "vs/platform/widget/browser/contextScopedHistoryWidget";
|
||||
import "vs/platform/label/electron-browser/label.contribution";
|
||||
import "vs/workbench/api/electron-browser/extensionHost.contribution";
|
||||
|
||||
// Menus/Actions
|
||||
import "vs/workbench/services/actions/electron-browser/menusExtensionPoint";
|
||||
import "vs/workbench/electron-browser/shell.contribution";
|
||||
import "vs/workbench/browser/workbench.contribution";
|
||||
|
||||
// Views
|
||||
import "vs/workbench/api/browser/viewsContainersExtensionPoint";
|
||||
import { startup } from "vs/workbench/electron-browser/main";
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region --- workbench actions
|
||||
|
||||
import "vs/workbench/browser/actions/layoutActions";
|
||||
import "vs/workbench/browser/actions/listCommands";
|
||||
import "vs/workbench/browser/actions/navigationActions";
|
||||
import "vs/workbench/browser/parts/quickopen/quickOpenActions";
|
||||
import "vs/workbench/browser/parts/quickinput/quickInputActions";
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region --- API Extension Points
|
||||
|
||||
import "vs/workbench/api/common/menusExtensionPoint";
|
||||
import "vs/workbench/api/common/configurationExtensionPoint";
|
||||
import "vs/workbench/api/browser/viewsExtensionPoint";
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region --- workbench services
|
||||
|
||||
import "vs/workbench/services/bulkEdit/electron-browser/bulkEditService";
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region --- workbench parts
|
||||
|
||||
// Localizations
|
||||
import "vs/workbench/parts/localizations/electron-browser/localizations.contribution";
|
||||
|
||||
// Workbench
|
||||
import "vs/workbench/browser/actions/toggleActivityBarVisibility";
|
||||
import "vs/workbench/browser/actions/toggleStatusbarVisibility";
|
||||
import "vs/workbench/browser/actions/toggleSidebarVisibility";
|
||||
import "vs/workbench/browser/actions/toggleSidebarPosition";
|
||||
import "vs/workbench/browser/actions/toggleEditorLayout";
|
||||
import "vs/workbench/browser/actions/toggleZenMode";
|
||||
import "vs/workbench/browser/actions/toggleCenteredLayout";
|
||||
import "vs/workbench/browser/actions/toggleTabsVisibility";
|
||||
// Preferences
|
||||
import "vs/workbench/parts/preferences/electron-browser/preferences.contribution";
|
||||
import "vs/workbench/parts/preferences/browser/keybindingsEditorContribution";
|
||||
|
||||
// Logs
|
||||
import "vs/workbench/parts/logs/electron-browser/logs.contribution";
|
||||
|
||||
import "vs/workbench/browser/parts/quickopen/quickopen.contribution";
|
||||
// Quick Open Handlers
|
||||
import "vs/workbench/parts/quickopen/browser/quickopen.contribution";
|
||||
import "vs/workbench/browser/parts/editor/editorPicker";
|
||||
import "vs/workbench/browser/parts/quickinput/quickInput.contribution";
|
||||
|
||||
// Explorer
|
||||
import "vs/workbench/parts/files/electron-browser/explorerViewlet";
|
||||
import "vs/workbench/parts/files/electron-browser/fileActions.contribution";
|
||||
import "vs/workbench/parts/files/electron-browser/files.contribution";
|
||||
|
||||
// Backup
|
||||
import "vs/workbench/parts/backup/common/backup.contribution";
|
||||
|
||||
// Stats
|
||||
import "vs/workbench/parts/stats/node/stats.contribution";
|
||||
|
||||
// Rapid Render Splash
|
||||
import "vs/workbench/parts/splash/electron-browser/partsSplash.contribution";
|
||||
|
||||
// Search
|
||||
import "vs/workbench/parts/search/electron-browser/search.contribution";
|
||||
import "vs/workbench/parts/search/browser/searchView";
|
||||
import "vs/workbench/parts/search/browser/openAnythingHandler";
|
||||
|
||||
// SCM
|
||||
import "vs/workbench/parts/scm/electron-browser/scm.contribution";
|
||||
import "vs/workbench/parts/scm/electron-browser/scmViewlet";
|
||||
|
||||
// Debug
|
||||
import "vs/workbench/parts/debug/electron-browser/debug.contribution";
|
||||
// import "vs/workbench/parts/debug/browser/debugQuickOpen";
|
||||
// import "vs/workbench/parts/debug/electron-browser/repl";
|
||||
// import "vs/workbench/parts/debug/browser/debugViewlet";
|
||||
import "vs/workbench/parts/debug/browser/debugQuickOpen";
|
||||
import "vs/workbench/parts/debug/electron-browser/repl";
|
||||
import "vs/workbench/parts/debug/browser/debugViewlet";
|
||||
|
||||
// Markers
|
||||
import "vs/workbench/parts/markers/electron-browser/markers.contribution";
|
||||
|
||||
// Comments
|
||||
import "vs/workbench/parts/comments/electron-browser/comments.contribution";
|
||||
|
||||
// HTML Preview
|
||||
import "vs/workbench/parts/html/electron-browser/html.contribution";
|
||||
|
||||
// URL Support
|
||||
import "vs/workbench/parts/url/electron-browser/url.contribution";
|
||||
|
||||
// Webview
|
||||
import "vs/workbench/parts/webview/electron-browser/webview.contribution";
|
||||
|
||||
import "vs/workbench/parts/welcome/walkThrough/electron-browser/walkThrough.contribution";
|
||||
|
||||
// Extensions Management
|
||||
import "vs/workbench/parts/extensions/electron-browser/extensions.contribution";
|
||||
import "vs/workbench/parts/extensions/browser/extensionsQuickOpen";
|
||||
import "vs/workbench/parts/extensions/electron-browser/extensionsViewlet";
|
||||
|
||||
import "vs/workbench/parts/welcome/page/electron-browser/welcomePage.contribution";
|
||||
|
||||
// Output Panel
|
||||
import "vs/workbench/parts/output/electron-browser/output.contribution";
|
||||
import "vs/workbench/parts/output/browser/outputPanel";
|
||||
|
||||
// Terminal
|
||||
import "vs/workbench/parts/terminal/electron-browser/terminal.contribution";
|
||||
import "vs/workbench/parts/terminal/browser/terminalQuickOpen";
|
||||
import "vs/workbench/parts/terminal/electron-browser/terminalPanel";
|
||||
|
||||
import "vs/workbench/electron-browser/workbench";
|
||||
|
||||
// import "vs/workbench/parts/relauncher/electron-browser/relauncher.contribution";
|
||||
// Relauncher
|
||||
import "vs/workbench/parts/relauncher/electron-browser/relauncher.contribution";
|
||||
|
||||
// Tasks
|
||||
import "vs/workbench/parts/tasks/electron-browser/task.contribution";
|
||||
|
||||
// Emmet
|
||||
import "vs/workbench/parts/emmet/browser/emmet.browser.contribution";
|
||||
import "vs/workbench/parts/emmet/electron-browser/emmet.contribution";
|
||||
|
||||
import "vs/workbench/parts/codeEditor/codeEditor.contribution";
|
||||
// CodeEditor Contributions
|
||||
import "vs/workbench/parts/codeEditor/electron-browser/codeEditor.contribution";
|
||||
|
||||
// Execution
|
||||
import "vs/workbench/parts/execution/electron-browser/execution.contribution";
|
||||
|
||||
// Snippets
|
||||
import "vs/workbench/parts/snippets/electron-browser/snippets.contribution";
|
||||
import "vs/workbench/parts/snippets/electron-browser/snippetsService";
|
||||
import "vs/workbench/parts/snippets/electron-browser/insertSnippet";
|
||||
import "vs/workbench/parts/snippets/electron-browser/configureSnippets";
|
||||
import "vs/workbench/parts/snippets/electron-browser/tabCompletion";
|
||||
|
||||
import "vs/workbench/parts/themes/electron-browser/themes.contribution";
|
||||
|
||||
// import "vs/workbench/parts/feedback/electron-browser/feedback.contribution";
|
||||
|
||||
import "vs/workbench/parts/welcome/gettingStarted/electron-browser/gettingStarted.contribution";
|
||||
// Send a Smile
|
||||
import "vs/workbench/parts/feedback/electron-browser/feedback.contribution";
|
||||
|
||||
// Update
|
||||
import "vs/workbench/parts/update/electron-browser/update.contribution";
|
||||
|
||||
// import "vs/workbench/parts/surveys/electron-browser/nps.contribution";
|
||||
// import "vs/workbench/parts/surveys/electron-browser/languageSurveys.contribution";
|
||||
// Surveys
|
||||
import "vs/workbench/parts/surveys/electron-browser/nps.contribution";
|
||||
import "vs/workbench/parts/surveys/electron-browser/languageSurveys.contribution";
|
||||
|
||||
// Performance
|
||||
import "vs/workbench/parts/performance/electron-browser/performance.contribution";
|
||||
|
||||
// import "vs/workbench/parts/cli/electron-browser/cli.contribution";
|
||||
// CLI
|
||||
import "vs/workbench/parts/cli/electron-browser/cli.contribution";
|
||||
|
||||
import "vs/workbench/api/electron-browser/extensionHost.contribution";
|
||||
|
||||
import "vs/workbench/electron-browser/main.contribution";
|
||||
import { startup } from "vs/workbench/electron-browser/main";
|
||||
|
||||
// import "vs/workbench/parts/themes/test/electron-browser/themes.test.contribution";
|
||||
// Themes Support
|
||||
import "vs/workbench/parts/themes/electron-browser/themes.contribution";
|
||||
import "vs/workbench/parts/themes/test/electron-browser/themes.test.contribution";
|
||||
|
||||
// Watermark
|
||||
import "vs/workbench/parts/watermark/electron-browser/watermark";
|
||||
|
||||
// Welcome
|
||||
import "vs/workbench/parts/welcome/walkThrough/electron-browser/walkThrough.contribution";
|
||||
import "vs/workbench/parts/welcome/gettingStarted/electron-browser/gettingStarted.contribution";
|
||||
import "vs/workbench/parts/welcome/overlay/browser/welcomeOverlay";
|
||||
import "vs/workbench/parts/welcome/page/electron-browser/welcomePage.contribution";
|
||||
|
||||
// Outline
|
||||
import "vs/workbench/parts/outline/electron-browser/outline.contribution";
|
||||
|
||||
import "vs/workbench/services/bulkEdit/electron-browser/bulkEditService";
|
||||
|
||||
// Experiments
|
||||
import "vs/workbench/parts/experiments/electron-browser/experiments.contribution";
|
||||
|
||||
//#endregion
|
||||
|
||||
import { URI } from "vs/base/common/uri";
|
||||
|
||||
export {
|
||||
|
4
scripts/build.sh
Executable file
4
scripts/build.sh
Executable file
@ -0,0 +1,4 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
yarn task build:server:binary
|
@ -1,8 +1,8 @@
|
||||
diff --git a/src/vs/code/electron-browser/sharedProcess/sharedProcessMain.ts b/src/vs/code/electron-browser/sharedProcess/sharedProcessMain.ts
|
||||
index 457818a975..ad45ffe58a 100644
|
||||
index a342222d04..c731e82591 100644
|
||||
--- a/src/vs/code/electron-browser/sharedProcess/sharedProcessMain.ts
|
||||
+++ b/src/vs/code/electron-browser/sharedProcess/sharedProcessMain.ts
|
||||
@@ -196,0 +197,2 @@ async function handshake(configuration: ISharedProcessConfiguration): Promise<vo
|
||||
@@ -195,0 +196,2 @@ async function handshake(configuration: ISharedProcessConfiguration): Promise<vo
|
||||
+
|
||||
+startup({ machineId: "1" });
|
||||
diff --git a/src/vs/editor/contrib/clipboard/clipboard.ts b/src/vs/editor/contrib/clipboard/clipboard.ts
|
||||
@ -38,10 +38,10 @@ index 5e43f1b39e..a008d3ac7e 100644
|
||||
+ }
|
||||
+ }
|
||||
diff --git a/src/vs/loader.js b/src/vs/loader.js
|
||||
index 2bf7fe37d7..81cc668f12 100644
|
||||
index 4eddcab3a0..5d80768406 100644
|
||||
--- a/src/vs/loader.js
|
||||
+++ b/src/vs/loader.js
|
||||
@@ -670,4 +670,4 @@ var AMDLoader;
|
||||
@@ -671,4 +671,4 @@ var AMDLoader;
|
||||
- this._fs = nodeRequire('fs');
|
||||
- this._vm = nodeRequire('vm');
|
||||
- this._path = nodeRequire('path');
|
||||
@ -50,7 +50,7 @@ index 2bf7fe37d7..81cc668f12 100644
|
||||
+ this._vm = require('vm');
|
||||
+ this._path = require('path');
|
||||
+ this._crypto = require('crypto');
|
||||
@@ -733,0 +734,7 @@ var AMDLoader;
|
||||
@@ -736,0 +737,7 @@ var AMDLoader;
|
||||
+ const context = require.context("../", true, /.*/);
|
||||
+ if (scriptSrc.indexOf("file:///") !== -1) {
|
||||
+ const vsSrc = scriptSrc.split("file:///")[1].split(".js")[0];
|
||||
@ -58,11 +58,11 @@ index 2bf7fe37d7..81cc668f12 100644
|
||||
+ scriptSrc = `node|./${vsSrc}`;
|
||||
+ }
|
||||
+ }
|
||||
@@ -738 +745 @@ var AMDLoader;
|
||||
@@ -741 +748 @@ var AMDLoader;
|
||||
- moduleExports_1 = nodeRequire(pieces[1]);
|
||||
+ moduleExports_1 = context(pieces[1]);
|
||||
diff --git a/src/vs/workbench/api/electron-browser/mainThreadHeapService.ts b/src/vs/workbench/api/electron-browser/mainThreadHeapService.ts
|
||||
index e3efb95b75..163bc4c994 100644
|
||||
index 6c52cbc937..09adbe7f51 100644
|
||||
--- a/src/vs/workbench/api/electron-browser/mainThreadHeapService.ts
|
||||
+++ b/src/vs/workbench/api/electron-browser/mainThreadHeapService.ts
|
||||
@@ -57,0 +58,3 @@ export class HeapService implements IHeapService {
|
||||
@ -70,24 +70,24 @@ index e3efb95b75..163bc4c994 100644
|
||||
+ return Promise.resolve(obj);
|
||||
+
|
||||
diff --git a/src/vs/workbench/api/node/extHostExtensionService.ts b/src/vs/workbench/api/node/extHostExtensionService.ts
|
||||
index 7841dcdaa2..f5665f0db3 100644
|
||||
index 1f4a1e100b..1bf605a064 100644
|
||||
--- a/src/vs/workbench/api/node/extHostExtensionService.ts
|
||||
+++ b/src/vs/workbench/api/node/extHostExtensionService.ts
|
||||
@@ -654 +654 @@ function loadCommonJSModule<T>(logService: ILogService, modulePath: string, acti
|
||||
@@ -719 +719 @@ function loadCommonJSModule<T>(logService: ILogService, modulePath: string, acti
|
||||
- r = require.__$__nodeRequire<T>(modulePath);
|
||||
+ r = (global as any).nativeNodeRequire(modulePath);
|
||||
diff --git a/src/vs/workbench/browser/dnd.ts b/src/vs/workbench/browser/dnd.ts
|
||||
index 38bf337a61..a6ee664a20 100644
|
||||
index e73acff052..bd65fcbd6c 100644
|
||||
--- a/src/vs/workbench/browser/dnd.ts
|
||||
+++ b/src/vs/workbench/browser/dnd.ts
|
||||
@@ -171 +171 @@ export class ResourcesDropHandler {
|
||||
- return;
|
||||
+ return (require('vs/../../../../packages/vscode') as typeof import ('vs/../../../../packages/vscode')).client.handleDrop(event, resolveTargetGroup, afterDrop, targetIndex);
|
||||
diff --git a/src/vs/workbench/electron-browser/main.ts b/src/vs/workbench/electron-browser/main.ts
|
||||
index a43d63aa51..438d0a8245 100644
|
||||
index 1e6333c731..0a7bdeeb9b 100644
|
||||
--- a/src/vs/workbench/electron-browser/main.ts
|
||||
+++ b/src/vs/workbench/electron-browser/main.ts
|
||||
@@ -150,7 +150,7 @@ function openWorkbench(configuration: IWindowConfiguration): Promise<void> {
|
||||
@@ -147,7 +147,7 @@ function openWorkbench(configuration: IWindowConfiguration): Promise<void> {
|
||||
- (<any>self).require.config({
|
||||
- onError: err => {
|
||||
- if (err.errorCode === 'load') {
|
||||
@ -103,27 +103,23 @@ index a43d63aa51..438d0a8245 100644
|
||||
+ // }
|
||||
+ // });
|
||||
diff --git a/src/vs/workbench/electron-browser/window.ts b/src/vs/workbench/electron-browser/window.ts
|
||||
index ea348f3a04..ada0003fea 100644
|
||||
index c0aff6bd4b..4f3b1e3984 100644
|
||||
--- a/src/vs/workbench/electron-browser/window.ts
|
||||
+++ b/src/vs/workbench/electron-browser/window.ts
|
||||
@@ -48 +48 @@ const TextInputActions: IAction[] = [
|
||||
- new Action('editor.action.clipboardPasteAction', nls.localize('paste', "Paste"), null, true, () => document.execCommand('paste') && Promise.resolve(true)),
|
||||
@@ -49 +49 @@ const TextInputActions: IAction[] = [
|
||||
- new Action('editor.action.clipboardPasteAction', nls.localize('paste', "Paste"), undefined, true, () => Promise.resolve(document.execCommand('paste'))),
|
||||
+ (require('vs/../../../../packages/vscode') as typeof import ('vs/../../../../packages/vscode')).client.pasteAction,
|
||||
@@ -263 +263 @@ export class ElectronWindow extends Themable {
|
||||
- (<any>window).open = function (url: string, target: string, features: string, replace: boolean): any {
|
||||
+ (<any>window).openInvalid = function (url: string, target: string, features: string, replace: boolean): any {
|
||||
diff --git a/src/vs/workbench/electron-browser/workbench.ts b/src/vs/workbench/electron-browser/workbench.ts
|
||||
index 35bc4a82b3..45e96001b6 100644
|
||||
index d82db96296..c9bd4e0325 100644
|
||||
--- a/src/vs/workbench/electron-browser/workbench.ts
|
||||
+++ b/src/vs/workbench/electron-browser/workbench.ts
|
||||
@@ -250,0 +251 @@ export class Workbench extends Disposable implements IPartService {
|
||||
@@ -272,0 +273 @@ export class Workbench extends Disposable implements IPartService {
|
||||
+ (require('vs/../../../../packages/vscode') as typeof import ('vs/../../../../packages/vscode')).client.serviceCollection = serviceCollection;
|
||||
diff --git a/src/vs/workbench/node/extensionHostProcess.ts b/src/vs/workbench/node/extensionHostProcess.ts
|
||||
index 8d182d18d9..69d51e1aea 100644
|
||||
--- a/src/vs/workbench/node/extensionHostProcess.ts
|
||||
+++ b/src/vs/workbench/node/extensionHostProcess.ts
|
||||
@@ -132 +132 @@ function connectToRenderer(protocol: IMessagePassingProtocol): Promise<IRenderer
|
||||
- process.kill(initData.parentPid, 0); // throws an exception if the main process doesn't exist anymore.
|
||||
+ // process.kill(initData.parentPid, 0); // throws an exception if the main process doesn't exist anymore.
|
||||
diff --git a/src/vs/workbench/parts/debug/node/debugAdapter.ts b/src/vs/workbench/parts/debug/node/debugAdapter.ts
|
||||
index 2d798bf2df..9ccadacb3a 100644
|
||||
index 81954344b9..2bdce9603e 100644
|
||||
--- a/src/vs/workbench/parts/debug/node/debugAdapter.ts
|
||||
+++ b/src/vs/workbench/parts/debug/node/debugAdapter.ts
|
||||
@@ -315 +315 @@ export class ExecutableDebugAdapter extends StreamDebugAdapter {
|
||||
@ -133,11 +129,11 @@ index 2d798bf2df..9ccadacb3a 100644
|
||||
- if (!fs.existsSync(this.adapterExecutable.command)) {
|
||||
+ if (!(await require("util").promisify(fs.exists)(this.adapterExecutable.command))) {
|
||||
diff --git a/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.ts b/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.ts
|
||||
index e600fb2f78..1e0dc9a220 100644
|
||||
index e66f74f034..aca6f509b0 100644
|
||||
--- a/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.ts
|
||||
+++ b/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.ts
|
||||
@@ -934,0 +935 @@ export class FileDragAndDrop extends SimpleFileResourceDragAndDrop {
|
||||
+ return (require('vs/../../../../packages/vscode') as typeof import ('vs/../../../../packages/vscode')).client.handleExternalDrop(target, originalEvent);
|
||||
@@ -586,0 +587 @@ export class FileDragAndDrop implements ITreeDragAndDrop<ExplorerItem> {
|
||||
+ return (require('vs/../../../../packages/vscode') as typeof import ('vs/../../../../packages/vscode')).client.handleExternalDrop(target, originalEvent as any);
|
||||
diff --git a/src/vs/workbench/parts/logs/electron-browser/logs.contribution.ts b/src/vs/workbench/parts/logs/electron-browser/logs.contribution.ts
|
||||
index 4015c9cd5d..bebdb25f6c 100644
|
||||
--- a/src/vs/workbench/parts/logs/electron-browser/logs.contribution.ts
|
||||
@ -147,14 +143,62 @@ index 4015c9cd5d..bebdb25f6c 100644
|
||||
+ // This channel only seems to be used when loading the app and we skip all of that, so it is never actually created or written to.
|
||||
+ // outputChannelRegistry.registerChannel({ id: Constants.mainLogChannelId, label: nls.localize('mainLog', "Main"), file: URI.file(join(environmentService.logsPath, `main.log`)), log: true });
|
||||
diff --git a/src/vs/workbench/parts/output/common/outputLinkProvider.ts b/src/vs/workbench/parts/output/common/outputLinkProvider.ts
|
||||
index 63437034c9..acd82c8375 100644
|
||||
index 6d9451401a..510f5131ce 100644
|
||||
--- a/src/vs/workbench/parts/output/common/outputLinkProvider.ts
|
||||
+++ b/src/vs/workbench/parts/output/common/outputLinkProvider.ts
|
||||
@@ -77,0 +78,2 @@ export class OutputLinkProvider {
|
||||
+ // TODO@coder: get this working.
|
||||
+
|
||||
+ return Promise.resolve([]);
|
||||
diff --git a/src/vs/workbench/parts/webview/electron-browser/webview-pre.js b/src/vs/workbench/parts/webview/electron-browser/webview-pre.js
|
||||
index 29593dc6b6..dd3d25098d 100644
|
||||
--- a/src/vs/workbench/parts/webview/electron-browser/webview-pre.js
|
||||
+++ b/src/vs/workbench/parts/webview/electron-browser/webview-pre.js
|
||||
@@ -10 +10,19 @@
|
||||
- const ipcRenderer = require('electron').ipcRenderer;
|
||||
+ const ipcRenderer = {
|
||||
+ on: (channel, callback) => {
|
||||
+ window.addEventListener("message", (event) => {
|
||||
+ if (event.data.channel === channel) {
|
||||
+ callback(event.data.channel, ...event.data.data);
|
||||
+ }
|
||||
+ });
|
||||
+ },
|
||||
+ sendToHost: (channel, ...args) => {
|
||||
+ window.parent.postMessage({
|
||||
+ channel,
|
||||
+ data: args,
|
||||
+ id: document.body.id,
|
||||
+ }, "*");
|
||||
+ },
|
||||
+ };
|
||||
+ const process = {
|
||||
+ pid: undefined,
|
||||
+ };
|
||||
@@ -22,7 +40,7 @@
|
||||
- require('electron').webFrame.registerURLSchemeAsPrivileged('vscode-resource', {
|
||||
- secure: true,
|
||||
- bypassCSP: false,
|
||||
- allowServiceWorkers: false,
|
||||
- supportFetchAPI: true,
|
||||
- corsEnabled: true
|
||||
- });
|
||||
+ // require('electron').webFrame.registerURLSchemeAsPrivileged('vscode-resource', {
|
||||
+ // secure: true,
|
||||
+ // bypassCSP: false,
|
||||
+ // allowServiceWorkers: false,
|
||||
+ // supportFetchAPI: true,
|
||||
+ // corsEnabled: true
|
||||
+ // });
|
||||
diff --git a/src/vs/workbench/parts/webview/electron-browser/webviewElement.ts b/src/vs/workbench/parts/webview/electron-browser/webviewElement.ts
|
||||
index 5d9110300f..ecdc40b0eb 100644
|
||||
--- a/src/vs/workbench/parts/webview/electron-browser/webviewElement.ts
|
||||
+++ b/src/vs/workbench/parts/webview/electron-browser/webviewElement.ts
|
||||
@@ -261,0 +262,3 @@ export class WebviewElement extends Disposable {
|
||||
+ Object.defineProperty(this._options, 'useSameOriginForRoot', {
|
||||
+ value: true,
|
||||
+ });
|
||||
diff --git a/src/vs/workbench/parts/welcome/walkThrough/node/walkThroughContentProvider.ts b/src/vs/workbench/parts/welcome/walkThrough/node/walkThroughContentProvider.ts
|
||||
index 7b4e8721ac..96d612f940 100644
|
||||
index 147f05b246..fa89583203 100644
|
||||
--- a/src/vs/workbench/parts/welcome/walkThrough/node/walkThroughContentProvider.ts
|
||||
+++ b/src/vs/workbench/parts/welcome/walkThrough/node/walkThroughContentProvider.ts
|
||||
@@ -31,6 +31,6 @@ export class WalkThroughContentProvider implements ITextModelContentProvider, IW
|
||||
@ -193,15 +237,22 @@ index 7b4e8721ac..96d612f940 100644
|
||||
- this.modelService.updateModel(codeEditorModel, content.value);
|
||||
+ this.modelService.updateModel(codeEditorModel, content);
|
||||
diff --git a/src/vs/workbench/services/extensions/electron-browser/cachedExtensionScanner.ts b/src/vs/workbench/services/extensions/electron-browser/cachedExtensionScanner.ts
|
||||
index 4cb7a231f3..78c87d13f6 100644
|
||||
index 29cbfd65c4..1091dc3c8a 100644
|
||||
--- a/src/vs/workbench/services/extensions/electron-browser/cachedExtensionScanner.ts
|
||||
+++ b/src/vs/workbench/services/extensions/electron-browser/cachedExtensionScanner.ts
|
||||
@@ -33,0 +34 @@ function getSystemExtensionsRoot(): string {
|
||||
+ return (require('vs/../../../../packages/vscode') as typeof import ('vs/../../../../packages/vscode')).client.builtInExtensionsDirectory;
|
||||
diff --git a/src/vs/workbench/services/themes/electron-browser/fileIconThemeData.ts b/src/vs/workbench/services/themes/electron-browser/fileIconThemeData.ts
|
||||
index 5b4136989f..25ccc0fe9e 100644
|
||||
--- a/src/vs/workbench/services/themes/electron-browser/fileIconThemeData.ts
|
||||
+++ b/src/vs/workbench/services/themes/electron-browser/fileIconThemeData.ts
|
||||
@@ -181 +181 @@ function _processIconThemeDocument(id: string, iconThemeDocumentLocation: URI, i
|
||||
- return resources.joinPath(iconThemeDocumentLocationDirname, path);
|
||||
+ return "/resource" + resources.joinPath(iconThemeDocumentLocationDirname, path).path;
|
||||
diff --git a/src/vs/workbench/services/extensions/node/extensionHostProcess.ts b/src/vs/workbench/services/extensions/node/extensionHostProcess.ts
|
||||
index 5f2935618c..af5498d7ac 100644
|
||||
--- a/src/vs/workbench/services/extensions/node/extensionHostProcess.ts
|
||||
+++ b/src/vs/workbench/services/extensions/node/extensionHostProcess.ts
|
||||
@@ -132 +132 @@ function connectToRenderer(protocol: IMessagePassingProtocol): Promise<IRenderer
|
||||
- process.kill(initData.parentPid, 0); // throws an exception if the main process doesn't exist anymore.
|
||||
+ // process.kill(initData.parentPid, 0); // throws an exception if the main process doesn't exist anymore.
|
||||
diff --git a/src/vs/workbench/workbench.main.ts b/src/vs/workbench/workbench.main.ts
|
||||
index 1ad274696d..f52d1e0d2e 100644
|
||||
--- a/src/vs/workbench/workbench.main.ts
|
||||
+++ b/src/vs/workbench/workbench.main.ts
|
||||
@@ -25 +25 @@ import 'vs/workbench/browser/actions/navigationActions';
|
||||
-import 'vs/workbench/browser/parts/quickopen/quickopenActions';
|
||||
+import 'vs/workbench/browser/parts/quickopen/quickOpenActions';
|
||||
|
@ -33,7 +33,7 @@ module.exports = (options = {}) => ({
|
||||
}],
|
||||
},
|
||||
}, {
|
||||
test: /\.(js)/,
|
||||
test: /\.(js|css)/,
|
||||
exclude: /test/,
|
||||
}, {
|
||||
test: /\.(txt|d\.ts|test.ts|perf.data.js|jxs|scpt|exe|sh|less)$/,
|
||||
@ -61,7 +61,7 @@ module.exports = (options = {}) => ({
|
||||
// pages or iframes so we don't need to include it here. Also excluding
|
||||
// markdown.css because even though it uses the file-loader as shown above
|
||||
// in the string replace, it's still making its way into the main CSS.
|
||||
exclude: /test|code\/electron-browser\/.+\.css$|markdown.css$/,
|
||||
exclude: /test|code\/electron-browser\/.+\.css$/,
|
||||
test: /\.s?css$/,
|
||||
// This is required otherwise it'll fail to resolve CSS in common.
|
||||
include: root,
|
||||
@ -73,7 +73,7 @@ module.exports = (options = {}) => ({
|
||||
loader: "sass-loader",
|
||||
}],
|
||||
}, {
|
||||
test: /\.(svg|png|ttf|woff|eot)$/,
|
||||
test: /\.(svg|png|ttf|woff|eot|woff2)$/,
|
||||
use: [{
|
||||
loader: "file-loader",
|
||||
options: {
|
||||
|
@ -4,6 +4,7 @@
|
||||
"module": "commonjs",
|
||||
"baseUrl": ".",
|
||||
"rootDir": ".",
|
||||
"jsx": "react",
|
||||
"outDir": "dist",
|
||||
"declaration": true,
|
||||
"sourceMap": true,
|
||||
|
54
yarn.lock
54
yarn.lock
@ -14,6 +14,23 @@
|
||||
dependencies:
|
||||
execa "^0.2.2"
|
||||
|
||||
"@types/fs-extra@^5.0.4":
|
||||
version "5.0.5"
|
||||
resolved "https://registry.yarnpkg.com/@types/fs-extra/-/fs-extra-5.0.5.tgz#080d90a792f3fa2c5559eb44bd8ef840aae9104b"
|
||||
integrity sha512-w7iqhDH9mN8eLClQOYTkhdYUOSpp25eXxfc6VbFOGtzxW34JcvctH2bKjj4jD4++z4R5iO5D+pg48W2e03I65A==
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/json5@^0.0.29":
|
||||
version "0.0.29"
|
||||
resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee"
|
||||
integrity sha1-7ihweulOEdK4J7y+UnC86n8+ce4=
|
||||
|
||||
"@types/node@*":
|
||||
version "11.9.4"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-11.9.4.tgz#ceb0048a546db453f6248f2d1d95e937a6f00a14"
|
||||
integrity sha512-Zl8dGvAcEmadgs1tmSPcvwzO1YRsz38bVJQvH1RvRqSR9/5n61Q1ktcDL0ht3FXWR+ZpVmXVwN1LuH4Ax23NsA==
|
||||
|
||||
"@types/node@^10.12.18":
|
||||
version "10.12.18"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-10.12.18.tgz#1d3ca764718915584fcd9f6344621b7672665c67"
|
||||
@ -1231,6 +1248,11 @@ deep-extend@^0.6.0:
|
||||
resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac"
|
||||
integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==
|
||||
|
||||
deepmerge@^2.0.1:
|
||||
version "2.2.1"
|
||||
resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-2.2.1.tgz#5d3ff22a01c00f645405a2fbc17d0778a1801170"
|
||||
integrity sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA==
|
||||
|
||||
default-gateway@^2.6.0:
|
||||
version "2.7.2"
|
||||
resolved "https://registry.yarnpkg.com/default-gateway/-/default-gateway-2.7.2.tgz#b7ef339e5e024b045467af403d50348db4642d0f"
|
||||
@ -1943,6 +1965,15 @@ fs-extra@^0.30.0:
|
||||
path-is-absolute "^1.0.0"
|
||||
rimraf "^2.2.8"
|
||||
|
||||
fs-extra@^7.0.1:
|
||||
version "7.0.1"
|
||||
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9"
|
||||
integrity sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==
|
||||
dependencies:
|
||||
graceful-fs "^4.1.2"
|
||||
jsonfile "^4.0.0"
|
||||
universalify "^0.1.0"
|
||||
|
||||
fs-minipass@^1.2.5:
|
||||
version "1.2.5"
|
||||
resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.5.tgz#06c277218454ec288df77ada54a03b8702aacb9d"
|
||||
@ -2835,6 +2866,13 @@ jsonfile@^2.1.0:
|
||||
optionalDependencies:
|
||||
graceful-fs "^4.1.6"
|
||||
|
||||
jsonfile@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb"
|
||||
integrity sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=
|
||||
optionalDependencies:
|
||||
graceful-fs "^4.1.6"
|
||||
|
||||
jsonify@~0.0.0:
|
||||
version "0.0.0"
|
||||
resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73"
|
||||
@ -5178,6 +5216,17 @@ ts-node@^7.0.1:
|
||||
source-map-support "^0.5.6"
|
||||
yn "^2.0.0"
|
||||
|
||||
tsconfig-paths@^3.8.0:
|
||||
version "3.8.0"
|
||||
resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.8.0.tgz#4e34202d5b41958f269cf56b01ed95b853d59f72"
|
||||
integrity sha512-zZEYFo4sjORK8W58ENkRn9s+HmQFkkwydDG7My5s/fnfr2YYCaiyXe/HBUcIgU8epEKOXwiahOO+KZYjiXlWyQ==
|
||||
dependencies:
|
||||
"@types/json5" "^0.0.29"
|
||||
deepmerge "^2.0.1"
|
||||
json5 "^1.0.1"
|
||||
minimist "^1.2.0"
|
||||
strip-bom "^3.0.0"
|
||||
|
||||
tslib@^1.8.0, tslib@^1.8.1, tslib@^1.9.0:
|
||||
version "1.9.3"
|
||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286"
|
||||
@ -5298,6 +5347,11 @@ unique-slug@^2.0.0:
|
||||
dependencies:
|
||||
imurmurhash "^0.1.4"
|
||||
|
||||
universalify@^0.1.0:
|
||||
version "0.1.2"
|
||||
resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66"
|
||||
integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==
|
||||
|
||||
unpipe@1.0.0, unpipe@~1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec"
|
||||
|
Reference in New Issue
Block a user