Part II
This commit is contained in:
parent
29417cd431
commit
779a5e6604
|
@ -1,6 +1,7 @@
|
|||
.git
|
||||
*.log
|
||||
.log
|
||||
.api-repl-history
|
||||
.lsp-repl-history
|
||||
node_modules
|
||||
out
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
import * as process from "process";
|
||||
|
||||
import * as JSON5 from "json5";
|
||||
import * as stringifyObject from "stringify-object";
|
||||
|
||||
import * as api from "./api";
|
||||
import { langs } from "./langs";
|
||||
import { mockSocket, startRepl } from "./util";
|
||||
|
||||
const args = process.argv.slice(2);
|
||||
|
||||
function die(msg: any) {
|
||||
console.error(msg);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
function printUsage() {
|
||||
console.log(`usage: yarn api-repl LANG`);
|
||||
}
|
||||
|
||||
if (args.length !== 1) {
|
||||
printUsage();
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (["-h", "-help", "--help", "help"].includes(args[0])) {
|
||||
printUsage();
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
const lang = args[0];
|
||||
|
||||
const config = langs[lang];
|
||||
if (!config) {
|
||||
console.error(`yarn api-repl: no such language: ${lang}`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const ws = mockSocket();
|
||||
ws.on("send", (data: string) => {
|
||||
try {
|
||||
data = stringifyObject(JSON.parse(data), { indent: "\0" })
|
||||
.replace(/\0/g, "")
|
||||
.replace(/\n/g, " ");
|
||||
} catch (err) {
|
||||
console.error(`Invalid JSON: ${err}`);
|
||||
}
|
||||
console.log("<<< " + data + "\n");
|
||||
});
|
||||
|
||||
startRepl({
|
||||
historyFile: ".api-repl-history",
|
||||
onLine: (line) => {
|
||||
let data;
|
||||
try {
|
||||
data = JSON5.parse(line);
|
||||
} catch (err) {
|
||||
console.error(`Invalid JSON: ${err}`);
|
||||
return;
|
||||
}
|
||||
console.log();
|
||||
ws.onMessage(JSON.stringify(data));
|
||||
},
|
||||
});
|
||||
|
||||
const session = new api.Session(ws as any, lang, (msg) =>
|
||||
console.log(msg + "\n")
|
||||
);
|
||||
session.setup().catch(die);
|
||||
|
||||
// https://www.w3schools.com/howto/howto_js_autocomplete.asp
|
|
@ -13,6 +13,9 @@ import { borrowUser } from "./users";
|
|||
import * as util from "./util";
|
||||
import { Context, Options, bash } from "./util";
|
||||
|
||||
const PACKAGE_MAX_SEARCH_RESULTS = 100;
|
||||
const PACKAGE_NAME_REGEX = /[-_a-zA-Z0-9.+:]/;
|
||||
|
||||
const allSessions: Set<Session> = new Set();
|
||||
|
||||
export class Session {
|
||||
|
@ -42,6 +45,12 @@ export class Session {
|
|||
input: string;
|
||||
output: string;
|
||||
} | null = null;
|
||||
packageSearcher: {
|
||||
proc: ChildProcess;
|
||||
live: boolean;
|
||||
input: string;
|
||||
output: string;
|
||||
} | null = null;
|
||||
|
||||
logPrimitive: (msg: string) => void;
|
||||
|
||||
|
@ -243,6 +252,9 @@ export class Session {
|
|||
this.logBadMessage(msg);
|
||||
break;
|
||||
}
|
||||
if (!this.config.format) {
|
||||
this.log("formatCode ignored because format is null");
|
||||
}
|
||||
await this.formatCode(msg.code);
|
||||
break;
|
||||
case "lspInput":
|
||||
|
@ -258,11 +270,22 @@ export class Session {
|
|||
break;
|
||||
case "ensure":
|
||||
if (!this.config.ensure) {
|
||||
this.log(`ensure ignored because of missing configuration`);
|
||||
this.log(`ensure ignored because ensure is null`);
|
||||
break;
|
||||
}
|
||||
await this.ensure(this.config.ensure);
|
||||
break;
|
||||
case "packageSearch":
|
||||
if (!this.config.pkg || !this.config.pkg.search) {
|
||||
this.log(`packageSearch ignored because pkg.search is null`);
|
||||
break;
|
||||
}
|
||||
if (typeof msg.search !== "string") {
|
||||
this.logBadMessage(msg);
|
||||
break;
|
||||
}
|
||||
await this.packageSearch(msg.search);
|
||||
break;
|
||||
default:
|
||||
this.logBadMessage(msg);
|
||||
break;
|
||||
|
@ -368,10 +391,6 @@ export class Session {
|
|||
|
||||
formatCode = async (code: string) => {
|
||||
try {
|
||||
if (!this.config.format) {
|
||||
this.log("formatCode ignored because format is null");
|
||||
return;
|
||||
}
|
||||
if (this.formatter) {
|
||||
const pid = this.formatter.proc.pid;
|
||||
const args = this.privilegedSpawn(
|
||||
|
@ -381,7 +400,7 @@ export class Session {
|
|||
this.formatter.live = false;
|
||||
this.formatter = null;
|
||||
}
|
||||
const args = this.privilegedSpawn(bash(this.config.format.run));
|
||||
const args = this.privilegedSpawn(bash(this.config.format!.run));
|
||||
const formatter = {
|
||||
proc: spawn(args[0], args.slice(1)),
|
||||
live: true,
|
||||
|
@ -440,6 +459,78 @@ export class Session {
|
|||
this.send({ event: "ensured", code });
|
||||
};
|
||||
|
||||
packageSearch = async (search: string) => {
|
||||
try {
|
||||
if (this.packageSearcher) {
|
||||
const pid = this.packageSearcher.proc.pid;
|
||||
const args = this.privilegedSpawn(
|
||||
bash(`kill -SIGTERM ${pid}; sleep 1; kill -SIGKILL ${pid}`)
|
||||
);
|
||||
spawn(args[0], args.slice(1));
|
||||
this.packageSearcher.live = false;
|
||||
this.packageSearcher = null;
|
||||
}
|
||||
if (!search) {
|
||||
this.send({
|
||||
event: "packageSearched",
|
||||
results: this.config.pkg!.popular || [],
|
||||
search: "",
|
||||
});
|
||||
return;
|
||||
}
|
||||
const args = this.privilegedSpawn(
|
||||
bash(this.config.pkg!.search!.replace(/NAME/g, search))
|
||||
);
|
||||
const packageSearcher = {
|
||||
proc: spawn(args[0], args.slice(1)),
|
||||
live: true,
|
||||
input: search,
|
||||
output: "",
|
||||
};
|
||||
packageSearcher.proc.stdout!.on("data", (data) => {
|
||||
if (!packageSearcher.live) return;
|
||||
packageSearcher.output += data.toString("utf8");
|
||||
});
|
||||
packageSearcher.proc.stderr!.on("data", (data) => {
|
||||
if (!packageSearcher.live) return;
|
||||
this.send({
|
||||
event: "serviceLog",
|
||||
service: "packageSearch",
|
||||
output: data.toString("utf8"),
|
||||
});
|
||||
});
|
||||
packageSearcher.proc.on("close", (code, signal) => {
|
||||
if (!packageSearcher.live) return;
|
||||
if (code === 0) {
|
||||
this.send({
|
||||
event: "packageSearched",
|
||||
results: packageSearcher.output.split("\n").filter((x) => x),
|
||||
search: packageSearcher.input,
|
||||
});
|
||||
} else {
|
||||
this.send({
|
||||
event: "serviceFailed",
|
||||
service: "packageSearch",
|
||||
error: `Exited with status ${signal || code}`,
|
||||
});
|
||||
}
|
||||
});
|
||||
packageSearcher.proc.on("error", (err) => {
|
||||
if (!packageSearcher.live) return;
|
||||
this.send({
|
||||
event: "serviceFailed",
|
||||
service: "packageSearch",
|
||||
error: `${err}`,
|
||||
});
|
||||
});
|
||||
this.packageSearcher = packageSearcher;
|
||||
} catch (err) {
|
||||
this.log(`Error while running package search`);
|
||||
console.log(err);
|
||||
this.sendError(err);
|
||||
}
|
||||
};
|
||||
|
||||
teardown = async () => {
|
||||
try {
|
||||
if (this.tearingDown) {
|
||||
|
|
|
@ -32,6 +32,7 @@ export interface LangConfig {
|
|||
output?: string;
|
||||
};
|
||||
pkg?: {
|
||||
index: string | string[];
|
||||
install: string;
|
||||
uninstall?: string;
|
||||
all?: string;
|
||||
|
@ -1928,6 +1929,7 @@ main = do
|
|||
`,
|
||||
},
|
||||
pkg: {
|
||||
index: "https://pypi.org/",
|
||||
install: "pip3 install --user NAME",
|
||||
uninstall: "pip3 uninstall NAME",
|
||||
search: `python3 -c 'import json; from xmlrpc import client; print(json.dumps(client.ServerProxy("https://pypi.org/pypi").search({"name": "NAME"})))' | jq -r 'map(.name) | .[]'`,
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
import * as child_process from "child_process";
|
||||
import * as process from "process";
|
||||
import * as nodeReadline from "readline";
|
||||
|
||||
import * as appRoot from "app-root-path";
|
||||
import * as readline from "historic-readline";
|
||||
import { quote } from "shell-quote";
|
||||
import * as rpc from "vscode-jsonrpc";
|
||||
|
||||
import { langs } from "./langs";
|
||||
import { startRepl } from "./util";
|
||||
|
||||
const args = process.argv.slice(2);
|
||||
|
||||
|
@ -57,56 +56,17 @@ reader.listen((data) => {
|
|||
console.log("<<< " + JSON.stringify(data) + "\n");
|
||||
});
|
||||
|
||||
// https://stackoverflow.com/a/10608048/3538165
|
||||
function fixStdoutFor(cli: any) {
|
||||
var oldStdout = process.stdout;
|
||||
var newStdout = Object.create(oldStdout);
|
||||
newStdout.write = function () {
|
||||
cli.output.write("\x1b[2K\r");
|
||||
var result = oldStdout.write.apply(
|
||||
this,
|
||||
(Array.prototype.slice as any).call(arguments)
|
||||
);
|
||||
cli._refreshLine();
|
||||
return result;
|
||||
};
|
||||
(process as any).__defineGetter__("stdout", function () {
|
||||
return newStdout;
|
||||
});
|
||||
}
|
||||
|
||||
readline.createInterface({
|
||||
input: process.stdin,
|
||||
output: process.stdout,
|
||||
path: appRoot.resolve(".lsp-repl-history"),
|
||||
next: (cli: nodeReadline.Interface) => {
|
||||
fixStdoutFor(cli);
|
||||
cli.setPrompt(">>> ");
|
||||
cli.on("line", (line: string) => {
|
||||
if (line) {
|
||||
let data;
|
||||
try {
|
||||
data = JSON.parse(line);
|
||||
} catch (err) {
|
||||
console.error(`Invalid JSON: ${err}`);
|
||||
cli.prompt();
|
||||
return;
|
||||
}
|
||||
console.log();
|
||||
writer.write(data);
|
||||
}
|
||||
cli.prompt();
|
||||
});
|
||||
cli.on("SIGINT", () => {
|
||||
console.error("^C");
|
||||
cli.write("", { ctrl: true, name: "u" });
|
||||
cli.prompt();
|
||||
});
|
||||
cli.on("close", () => {
|
||||
console.error();
|
||||
process.exit(0);
|
||||
});
|
||||
startRepl({
|
||||
historyFile: ".lsp-repl-history",
|
||||
onLine: (line) => {
|
||||
let data;
|
||||
try {
|
||||
data = JSON.parse(line);
|
||||
} catch (err) {
|
||||
console.error(`Invalid JSON: ${err}`);
|
||||
return;
|
||||
}
|
||||
console.log();
|
||||
cli.prompt();
|
||||
writer.write(data);
|
||||
},
|
||||
});
|
||||
|
|
|
@ -11,6 +11,7 @@ import { v4 as getUUID } from "uuid";
|
|||
|
||||
import * as api from "./api";
|
||||
import { LangConfig, langs } from "./langs";
|
||||
import { mockSocket } from "./util";
|
||||
|
||||
function parseIntOr(thing: any, def: number) {
|
||||
const num = parseInt(thing);
|
||||
|
@ -88,35 +89,11 @@ class Test {
|
|||
let session = null;
|
||||
let timeout = null;
|
||||
try {
|
||||
const that = this;
|
||||
this.ws = {
|
||||
on: function (type: string, handler: any) {
|
||||
switch (type) {
|
||||
case "message":
|
||||
this.onMessage = handler;
|
||||
for (const msg of this.messageQueue) {
|
||||
this.onMessage(msg);
|
||||
}
|
||||
this.messageQueue = [];
|
||||
break;
|
||||
case "close":
|
||||
case "error":
|
||||
// No need to clean up, we'll call teardown() explicitly.
|
||||
break;
|
||||
default:
|
||||
throw new Error(`unexpected websocket handler type: ${type}`);
|
||||
}
|
||||
},
|
||||
onMessage: function (msg: any) {
|
||||
this.messageQueue.push(msg);
|
||||
},
|
||||
messageQueue: [] as any[],
|
||||
send: function (data: string) {
|
||||
that.record(JSON.parse(data));
|
||||
that.handleUpdate();
|
||||
},
|
||||
terminate: function () {},
|
||||
};
|
||||
this.ws = mockSocket();
|
||||
this.ws.on("send", (data: string) => {
|
||||
this.record(JSON.parse(data));
|
||||
this.handleUpdate();
|
||||
});
|
||||
session = new api.Session(this.ws, this.lang, (msg: string) => {
|
||||
this.record({ event: "serverLog", message: msg });
|
||||
});
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
import { SpawnOptions, spawn, spawnSync } from "child_process";
|
||||
import * as os from "os";
|
||||
import * as process from "process";
|
||||
import * as nodeReadline from "readline";
|
||||
|
||||
import * as appRoot from "app-root-path";
|
||||
import * as readline from "historic-readline";
|
||||
import { quote } from "shell-quote";
|
||||
|
||||
import { MIN_UID, MAX_UID } from "./users";
|
||||
|
@ -138,3 +140,93 @@ export function bash(cmdline: string) {
|
|||
}
|
||||
return ["bash", "-c", cmdline];
|
||||
}
|
||||
|
||||
// https://stackoverflow.com/a/10608048/3538165
|
||||
function fixStreamFor(cli: any, streamName: string) {
|
||||
var oldStream = (process as any)[streamName];
|
||||
var newStream = Object.create(oldStream);
|
||||
newStream.write = function () {
|
||||
cli.output.write("\x1b[2K\r");
|
||||
var result = oldStream.write.apply(
|
||||
this,
|
||||
(Array.prototype.slice as any).call(arguments)
|
||||
);
|
||||
cli._refreshLine();
|
||||
return result;
|
||||
};
|
||||
(process as any).__defineGetter__("old" + streamName, () => oldStream);
|
||||
(process as any).__defineGetter__(streamName, () => newStream);
|
||||
}
|
||||
|
||||
export interface ReplOptions {
|
||||
onLine: (line: any) => void;
|
||||
historyFile: string;
|
||||
}
|
||||
|
||||
export function startRepl(options: ReplOptions) {
|
||||
readline.createInterface({
|
||||
input: process.stdin,
|
||||
output: process.stdout,
|
||||
path: appRoot.resolve(options.historyFile),
|
||||
next: (cli: nodeReadline.Interface) => {
|
||||
fixStreamFor(cli, "stdout");
|
||||
fixStreamFor(cli, "stderr");
|
||||
cli.setPrompt(">>> ");
|
||||
cli.on("line", (line: string) => {
|
||||
if (line) {
|
||||
options.onLine(line);
|
||||
}
|
||||
cli.prompt();
|
||||
});
|
||||
cli.on("SIGINT", () => {
|
||||
(process as any).oldstderr.write("^C\n");
|
||||
cli.write("", { ctrl: true, name: "u" });
|
||||
cli.prompt();
|
||||
});
|
||||
cli.on("close", () => {
|
||||
(process as any).oldstderr.write("^D\n");
|
||||
process.exit(0);
|
||||
});
|
||||
console.log();
|
||||
cli.prompt();
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function mockSocket() {
|
||||
return {
|
||||
on: function (type: string, handler: any) {
|
||||
switch (type) {
|
||||
case "message":
|
||||
this.onMessage = handler;
|
||||
for (const msg of this.messageReceivedQueue) {
|
||||
this.onMessage(msg);
|
||||
}
|
||||
this.messageReceivedQueue = [];
|
||||
break;
|
||||
case "send":
|
||||
this.send = handler;
|
||||
for (const msg of this.messageSentQueue) {
|
||||
this.send(msg);
|
||||
}
|
||||
this.messageSentQueue = [];
|
||||
break;
|
||||
case "close":
|
||||
case "error":
|
||||
// No need to clean up, we'll call teardown() explicitly.
|
||||
break;
|
||||
default:
|
||||
throw new Error(`unexpected websocket handler type: ${type}`);
|
||||
}
|
||||
},
|
||||
onMessage: function (msg: any) {
|
||||
this.messageReceivedQueue.push(msg);
|
||||
},
|
||||
send: function (msg: any) {
|
||||
this.messageSentQueue.push(msg);
|
||||
},
|
||||
messageReceivedQueue: [] as any[],
|
||||
messageSentQueue: [] as any[],
|
||||
terminate: function () {},
|
||||
};
|
||||
}
|
||||
|
|
|
@ -37,17 +37,16 @@
|
|||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form autocomplete="off">
|
||||
<input type="button" class="btn btn-primary" value="Add package" id="packagesAdd"/>
|
||||
<div id="packagesSearchContainer">
|
||||
<input
|
||||
type="text"
|
||||
class="form-control shadow-none"
|
||||
placeholder="Search for packages..."
|
||||
id="packagesSearch"
|
||||
/>
|
||||
</div>
|
||||
</form>
|
||||
<input type="button" class="btn btn-primary" value="Add package" id="packagesAdd"/>
|
||||
<div id="packagesSearchContainer">
|
||||
<input
|
||||
type="text"
|
||||
class="form-control shadow-none"
|
||||
placeholder="Search for packages..."
|
||||
id="packagesSearch"
|
||||
autocomplete="off"
|
||||
/>
|
||||
</div>
|
||||
<hr/>
|
||||
<div id="packagesTerminal"></div>
|
||||
</div>
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import * as $ from "jquery";
|
||||
import * as _ from "lodash";
|
||||
import * as monaco from "monaco-editor";
|
||||
import {
|
||||
createConnection,
|
||||
|
@ -138,6 +139,7 @@ async function main() {
|
|||
window.addEventListener("resize", () => fitAddon.fit());
|
||||
|
||||
let packagesTermOpened = false;
|
||||
let handlePackageSearchResults: (results: string[]) => void = () => {};
|
||||
|
||||
await new Promise((resolve) =>
|
||||
term.write("Connecting to server...", resolve)
|
||||
|
@ -284,7 +286,24 @@ async function main() {
|
|||
}
|
||||
return;
|
||||
case "serviceCrashed":
|
||||
if (typeof message.service !== "string") {
|
||||
console.error("Unexpected message from server:", message);
|
||||
return;
|
||||
}
|
||||
if (message.service === "packageSearch") {
|
||||
handlePackageSearchResults([]);
|
||||
}
|
||||
return;
|
||||
case "packageSearched":
|
||||
if (
|
||||
!Array.isArray(message.results) ||
|
||||
!message.results.every((x: any) => typeof x === "string")
|
||||
) {
|
||||
console.error("Unexpected message from server:", message);
|
||||
return;
|
||||
}
|
||||
handlePackageSearchResults(message.results);
|
||||
break;
|
||||
default:
|
||||
console.error("Unexpected message from server:", message);
|
||||
return;
|
||||
|
@ -342,21 +361,34 @@ async function main() {
|
|||
}
|
||||
if (config.pkg) {
|
||||
document.getElementById("packagesButton")!.classList.add("visible");
|
||||
$("#packagesModal").on("shown.bs.modal", () => {
|
||||
if (!packagesTermOpened) {
|
||||
packagesTermOpened = true;
|
||||
|
||||
const packagesTerm = new Terminal();
|
||||
const packagesFitAddon = new FitAddon();
|
||||
packagesTerm.loadAddon(packagesFitAddon);
|
||||
|
||||
packagesTerm.open(document.getElementById("packagesTerminal")!);
|
||||
|
||||
packagesFitAddon.fit();
|
||||
window.addEventListener("resize", () => packagesFitAddon.fit());
|
||||
|
||||
const searchInput = document.getElementById(
|
||||
"packagesSearch"
|
||||
) as HTMLInputElement;
|
||||
searchInput.addEventListener(
|
||||
"input",
|
||||
_.debounce(() => {
|
||||
sendMessage({ event: "packageSearch", search: searchInput.value });
|
||||
}, 100)
|
||||
);
|
||||
handlePackageSearchResults = (results: string[]) => {
|
||||
console.log("got results:", results);
|
||||
};
|
||||
}
|
||||
});
|
||||
}
|
||||
$("#packagesModal").on("shown.bs.modal", () => {
|
||||
if (!packagesTermOpened) {
|
||||
packagesTermOpened = true;
|
||||
|
||||
const packagesTerm = new Terminal();
|
||||
const packagesFitAddon = new FitAddon();
|
||||
packagesTerm.loadAddon(packagesFitAddon);
|
||||
|
||||
packagesTerm.open(document.getElementById("packagesTerminal")!);
|
||||
|
||||
packagesFitAddon.fit();
|
||||
window.addEventListener("resize", () => packagesFitAddon.fit());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
main().catch(console.error);
|
||||
|
|
|
@ -11,12 +11,14 @@
|
|||
"@types/express": "^4.17.6",
|
||||
"@types/express-ws": "^3.0.0",
|
||||
"@types/jquery": "^3.5.1",
|
||||
"@types/json5": "^0.0.30",
|
||||
"@types/lodash": "^4.14.155",
|
||||
"@types/mkdirp": "^1.0.1",
|
||||
"@types/node-cleanup": "^2.1.1",
|
||||
"@types/parse-passwd": "^1.0.0",
|
||||
"@types/rimraf": "^3.0.0",
|
||||
"@types/shell-quote": "^1.7.0",
|
||||
"@types/stringify-object": "^3.3.0",
|
||||
"@types/tmp": "^0.2.0",
|
||||
"@types/uuid": "^8.0.0",
|
||||
"app-root-path": "^3.0.0",
|
||||
|
@ -30,7 +32,8 @@
|
|||
"file-loader": "^6.0.0",
|
||||
"historic-readline": "^1.0.8",
|
||||
"jquery": "^3.5.1",
|
||||
"lodash": "^4.17.15",
|
||||
"json5": "^2.1.3",
|
||||
"lodash": "^4.17.20",
|
||||
"moment": "^2.27.0",
|
||||
"monaco-editor": "^0.20.0",
|
||||
"monaco-editor-webpack-plugin": "^1.9.0",
|
||||
|
@ -42,6 +45,7 @@
|
|||
"popper.js": "^1.16.1",
|
||||
"rimraf": "^3.0.2",
|
||||
"shell-quote": "^1.7.2",
|
||||
"stringify-object": "^3.3.0",
|
||||
"style-loader": "^1.2.1",
|
||||
"ts-loader": "^7.0.5",
|
||||
"typescript": "^3.9.5",
|
||||
|
@ -64,6 +68,7 @@
|
|||
"system-dev": "watchexec --no-vcs-ignore -w system/src -n scripts/compile-system.bash",
|
||||
"build": "run-s backend frontend system",
|
||||
"dev": "run-p backend-dev frontend-dev system-dev server-dev",
|
||||
"api-repl": "node backend/out/api-repl.js",
|
||||
"lsp-repl": "node backend/out/lsp-repl.js",
|
||||
"sandbox": "node backend/out/sandbox.js",
|
||||
"test": "bash -c 'scripts/setup.bash && time node backend/out/test-runner.js \"$@\"' --"
|
||||
|
|
43
yarn.lock
43
yarn.lock
|
@ -867,6 +867,11 @@
|
|||
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.4.tgz#38fd73ddfd9b55abb1e1b2ed578cb55bd7b7d339"
|
||||
integrity sha512-8+KAKzEvSUdeo+kmqnKrqgeE+LcA0tjYWFY7RPProVYwnqDjukzO+3b6dLD56rYX5TdWejnEOLJYOIeh4CXKuA==
|
||||
|
||||
"@types/json5@^0.0.30":
|
||||
version "0.0.30"
|
||||
resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.30.tgz#44cb52f32a809734ca562e685c6473b5754a7818"
|
||||
integrity sha512-sqm9g7mHlPY/43fcSNrCYfOeX9zkTTK+euO5E6+CVijSMm5tTjkVdwdqRkY3ljjIAf8679vps5jKUoJBCLsMDA==
|
||||
|
||||
"@types/lodash@^4.14.155":
|
||||
version "4.14.155"
|
||||
resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.155.tgz#e2b4514f46a261fd11542e47519c20ebce7bc23a"
|
||||
|
@ -940,6 +945,11 @@
|
|||
resolved "https://registry.yarnpkg.com/@types/sizzle/-/sizzle-2.3.2.tgz#a811b8c18e2babab7d542b3365887ae2e4d9de47"
|
||||
integrity sha512-7EJYyKTL7tFR8+gDbB6Wwz/arpGa0Mywk1TJbNzKzHtzbwVmY4HR9WqS5VV7dsBUKQmPNr192jHr/VpBluj/hg==
|
||||
|
||||
"@types/stringify-object@^3.3.0":
|
||||
version "3.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/stringify-object/-/stringify-object-3.3.0.tgz#7ea04ff326e7c549fe311eae8f26e6211c880498"
|
||||
integrity sha512-ryxTolaNg1l809rknW9q9T7wG8QHcjtZX6syJx7kpOLY2qev75VzC9HMVimUxlA1YzjpGsDI29yLjHBotqhUhA==
|
||||
|
||||
"@types/tmp@^0.2.0":
|
||||
version "0.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/tmp/-/tmp-0.2.0.tgz#e3f52b4d7397eaa9193592ef3fdd44dc0af4298c"
|
||||
|
@ -2447,6 +2457,11 @@ get-caller-file@^2.0.1:
|
|||
resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e"
|
||||
integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==
|
||||
|
||||
get-own-enumerable-property-symbols@^3.0.0:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz#b5fde77f22cbe35f390b4e089922c50bce6ef664"
|
||||
integrity sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==
|
||||
|
||||
get-stream@^4.0.0:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5"
|
||||
|
@ -2937,6 +2952,11 @@ is-number@^7.0.0:
|
|||
resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b"
|
||||
integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==
|
||||
|
||||
is-obj@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f"
|
||||
integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8=
|
||||
|
||||
is-plain-object@^2.0.3, is-plain-object@^2.0.4:
|
||||
version "2.0.4"
|
||||
resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677"
|
||||
|
@ -2951,6 +2971,11 @@ is-regex@^1.1.0:
|
|||
dependencies:
|
||||
has-symbols "^1.0.1"
|
||||
|
||||
is-regexp@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/is-regexp/-/is-regexp-1.0.0.tgz#fd2d883545c46bac5a633e7b9a09e87fa2cb5069"
|
||||
integrity sha1-/S2INUXEa6xaYz57mgnof6LLUGk=
|
||||
|
||||
is-stream@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44"
|
||||
|
@ -3042,7 +3067,7 @@ json5@^1.0.1:
|
|||
dependencies:
|
||||
minimist "^1.2.0"
|
||||
|
||||
json5@^2.1.2:
|
||||
json5@^2.1.2, json5@^2.1.3:
|
||||
version "2.1.3"
|
||||
resolved "https://registry.yarnpkg.com/json5/-/json5-2.1.3.tgz#c9b0f7fa9233bfe5807fe66fcf3a5617ed597d43"
|
||||
integrity sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==
|
||||
|
@ -3157,11 +3182,16 @@ locate-path@^3.0.0:
|
|||
p-locate "^3.0.0"
|
||||
path-exists "^3.0.0"
|
||||
|
||||
lodash@^4.17.13, lodash@^4.17.15:
|
||||
lodash@^4.17.13:
|
||||
version "4.17.15"
|
||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548"
|
||||
integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==
|
||||
|
||||
lodash@^4.17.20:
|
||||
version "4.17.20"
|
||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52"
|
||||
integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==
|
||||
|
||||
loose-envify@^1.0.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
|
||||
|
@ -4590,6 +4620,15 @@ string_decoder@~1.1.1:
|
|||
dependencies:
|
||||
safe-buffer "~5.1.0"
|
||||
|
||||
stringify-object@^3.3.0:
|
||||
version "3.3.0"
|
||||
resolved "https://registry.yarnpkg.com/stringify-object/-/stringify-object-3.3.0.tgz#703065aefca19300d3ce88af4f5b3956d7556629"
|
||||
integrity sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==
|
||||
dependencies:
|
||||
get-own-enumerable-property-symbols "^3.0.0"
|
||||
is-obj "^1.0.1"
|
||||
is-regexp "^1.0.0"
|
||||
|
||||
strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0:
|
||||
version "5.2.0"
|
||||
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae"
|
||||
|
|
Loading…
Reference in New Issue