Fix loading within the CLI (#27)
* Fix loading within the CLI * Remove app * Remove promise handle * Fix requested changes
This commit is contained in:
@ -4,7 +4,8 @@
|
||||
"dependencies": {
|
||||
"express": "^4.16.4",
|
||||
"google-protobuf": "^3.6.1",
|
||||
"node-pty": "^0.8.0",
|
||||
"node-pty": "^0.8.1",
|
||||
"tslib": "^1.9.3",
|
||||
"ws": "^6.1.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
@ -327,6 +327,7 @@ export class Client {
|
||||
workingDirectory: init.getWorkingDirectory(),
|
||||
os: opSys,
|
||||
shell: init.getShell(),
|
||||
builtInExtensionsDirectory: init.getBuiltinExtensionsDir(),
|
||||
};
|
||||
this.initDataEmitter.emit(this._initData);
|
||||
} else if (message.hasEvalDone()) {
|
||||
|
@ -8,6 +8,7 @@ import { Client } from "../client";
|
||||
// Use this to get around Webpack inserting our fills.
|
||||
// TODO: is there a better way?
|
||||
declare var _require: typeof require;
|
||||
declare var _Buffer: typeof Buffer;
|
||||
|
||||
/**
|
||||
* Implements the native fs module
|
||||
@ -121,7 +122,7 @@ export class FS {
|
||||
const ae = this.client.run((ae, path, options) => {
|
||||
const fs = _require("fs") as typeof import("fs");
|
||||
const str = fs.createWriteStream(path, options);
|
||||
ae.on("write", (d, e) => str.write(Buffer.from(d, e)));
|
||||
ae.on("write", (d, e) => str.write(_Buffer.from(d, "utf8")));
|
||||
ae.on("close", () => str.close());
|
||||
str.on("close", () => ae.emit("close"));
|
||||
str.on("open", (fd) => ae.emit("open", fd));
|
||||
@ -216,18 +217,18 @@ export class FS {
|
||||
this.client.evaluate((fd) => {
|
||||
const fs = _require("fs") as typeof import("fs");
|
||||
const util = _require("util") as typeof import("util");
|
||||
const tslib = _require("tslib") as typeof import("tslib");
|
||||
|
||||
return util.promisify(fs.fstat)(fd).then((stats) => {
|
||||
return {
|
||||
...stats,
|
||||
_isBlockDevice: stats.isBlockDevice(),
|
||||
_isCharacterDevice: stats.isCharacterDevice(),
|
||||
return tslib.__assign(stats, {
|
||||
_isBlockDevice: stats.isBlockDevice ? stats.isBlockDevice() : false,
|
||||
_isCharacterDevice: stats.isCharacterDevice ? stats.isCharacterDevice() : false,
|
||||
_isDirectory: stats.isDirectory(),
|
||||
_isFIFO: stats.isFIFO(),
|
||||
_isFIFO: stats.isFIFO ? stats.isFIFO() : false,
|
||||
_isFile: stats.isFile(),
|
||||
_isSocket: stats.isSocket(),
|
||||
_isSymbolicLink: stats.isSymbolicLink(),
|
||||
};
|
||||
_isSocket: stats.isSocket ? stats.isSocket() : false,
|
||||
_isSymbolicLink: stats.isSymbolicLink ? stats.isSymbolicLink() : false,
|
||||
});
|
||||
});
|
||||
}, fd).then((stats) => {
|
||||
callback(undefined!, new Stats(stats));
|
||||
@ -322,18 +323,18 @@ export class FS {
|
||||
this.client.evaluate((path) => {
|
||||
const fs = _require("fs") as typeof import("fs");
|
||||
const util = _require("util") as typeof import("util");
|
||||
const tslib = _require("tslib") as typeof import("tslib");
|
||||
|
||||
return util.promisify(fs.lstat)(path).then((stats) => {
|
||||
return {
|
||||
...stats,
|
||||
_isBlockDevice: stats.isBlockDevice(),
|
||||
_isCharacterDevice: stats.isCharacterDevice(),
|
||||
return tslib.__assign(stats, {
|
||||
_isBlockDevice: stats.isBlockDevice ? stats.isBlockDevice() : false,
|
||||
_isCharacterDevice: stats.isCharacterDevice ? stats.isCharacterDevice() : false,
|
||||
_isDirectory: stats.isDirectory(),
|
||||
_isFIFO: stats.isFIFO(),
|
||||
_isFIFO: stats.isFIFO ? stats.isFIFO() : false,
|
||||
_isFile: stats.isFile(),
|
||||
_isSocket: stats.isSocket(),
|
||||
_isSymbolicLink: stats.isSymbolicLink(),
|
||||
};
|
||||
_isSocket: stats.isSocket ? stats.isSocket() : false,
|
||||
_isSymbolicLink: stats.isSymbolicLink ? stats.isSymbolicLink() : false,
|
||||
});
|
||||
});
|
||||
}, path).then((stats) => {
|
||||
callback(undefined!, new Stats(stats));
|
||||
@ -397,7 +398,7 @@ export class FS {
|
||||
this.client.evaluate((fd, length, position) => {
|
||||
const fs = _require("fs") as typeof import("fs");
|
||||
const util = _require("util") as typeof import("util");
|
||||
const buffer = new Buffer(length);
|
||||
const buffer = new _Buffer(length);
|
||||
|
||||
return util.promisify(fs.read)(fd, buffer, 0, length, position).then((resp) => {
|
||||
return {
|
||||
@ -513,18 +514,22 @@ export class FS {
|
||||
this.client.evaluate((path) => {
|
||||
const fs = _require("fs") as typeof import("fs");
|
||||
const util = _require("util") as typeof import("util");
|
||||
const tslib = _require("tslib") as typeof import("tslib");
|
||||
|
||||
return util.promisify(fs.stat)(path).then((stats) => {
|
||||
return {
|
||||
...stats,
|
||||
_isBlockDevice: stats.isBlockDevice(),
|
||||
_isCharacterDevice: stats.isCharacterDevice(),
|
||||
return tslib.__assign(stats, {
|
||||
/**
|
||||
* We need to check if functions exist because nexe's implemented FS
|
||||
* lib doesnt implement fs.stats properly
|
||||
*/
|
||||
_isBlockDevice: stats.isBlockDevice ? stats.isBlockDevice() : false,
|
||||
_isCharacterDevice: stats.isCharacterDevice ? stats.isCharacterDevice() : false,
|
||||
_isDirectory: stats.isDirectory(),
|
||||
_isFIFO: stats.isFIFO(),
|
||||
_isFIFO: stats.isFIFO ? stats.isFIFO() : false,
|
||||
_isFile: stats.isFile(),
|
||||
_isSocket: stats.isSocket(),
|
||||
_isSymbolicLink: stats.isSymbolicLink(),
|
||||
};
|
||||
_isSocket: stats.isSocket ? stats.isSocket() : false,
|
||||
_isSymbolicLink: stats.isSymbolicLink ? stats.isSymbolicLink() : false,
|
||||
});
|
||||
});
|
||||
}, path).then((stats) => {
|
||||
callback(undefined!, new Stats(stats));
|
||||
@ -602,7 +607,7 @@ export class FS {
|
||||
const fs = _require("fs") as typeof import("fs");
|
||||
const util = _require("util") as typeof import("util");
|
||||
|
||||
return util.promisify(fs.write)(fd, Buffer.from(buffer, "utf8"), offset, length, position).then((resp) => {
|
||||
return util.promisify(fs.write)(fd, _Buffer.from(buffer, "utf8"), offset, length, position).then((resp) => {
|
||||
return {
|
||||
bytesWritten: resp.bytesWritten,
|
||||
content: resp.buffer.toString("utf8"),
|
||||
|
@ -21,6 +21,7 @@ export interface InitData {
|
||||
readonly homeDirectory: string;
|
||||
readonly tmpDirectory: string;
|
||||
readonly shell: string;
|
||||
readonly builtInExtensionsDirectory: string;
|
||||
}
|
||||
|
||||
export interface ISharedProcessData {
|
||||
|
@ -1,6 +1,5 @@
|
||||
import * as cp from "child_process";
|
||||
import * as net from "net";
|
||||
import * as nodePty from "node-pty";
|
||||
import * as stream from "stream";
|
||||
import { TextEncoder } from "text-encoding";
|
||||
import { Logger, logger, field } from "@coder/logger";
|
||||
@ -44,6 +43,7 @@ export const handleNewSession = (connection: SendableConnection, newSession: New
|
||||
});
|
||||
if (newSession.getTtyDimensions()) {
|
||||
// Spawn with node-pty
|
||||
const nodePty = require("node-pty") as typeof import("node-pty");
|
||||
const ptyProc = nodePty.spawn(newSession.getCommand(), newSession.getArgsList(), {
|
||||
cols: newSession.getTtyDimensions()!.getWidth(),
|
||||
rows: newSession.getTtyDimensions()!.getHeight(),
|
||||
@ -56,7 +56,7 @@ export const handleNewSession = (connection: SendableConnection, newSession: New
|
||||
processTitle = ptyProc.process;
|
||||
const id = new IdentifySessionMessage();
|
||||
id.setId(newSession.getId());
|
||||
id.setTitle(processTitle);
|
||||
id.setTitle(processTitle!);
|
||||
const sm = new ServerMessage();
|
||||
sm.setIdentifySession(id);
|
||||
connection.send(sm.serializeBinary());
|
||||
|
@ -76,7 +76,7 @@ export const evaluate = (connection: SendableConnection, message: NewEvalMessage
|
||||
connection.send(serverMsg.serializeBinary());
|
||||
},
|
||||
} : undefined,
|
||||
Buffer,
|
||||
_Buffer: Buffer,
|
||||
require: typeof __non_webpack_require__ !== "undefined" ? __non_webpack_require__ : require,
|
||||
_require: typeof __non_webpack_require__ !== "undefined" ? __non_webpack_require__ : require,
|
||||
tslib_1: require("tslib"), // TODO: is there a better way to do this?
|
||||
@ -98,7 +98,7 @@ export const evaluate = (connection: SendableConnection, message: NewEvalMessage
|
||||
onDispose();
|
||||
}
|
||||
} catch (ex) {
|
||||
sendErr(EvalFailedMessage.Reason.EXCEPTION, ex.toString());
|
||||
sendErr(EvalFailedMessage.Reason.EXCEPTION, ex.toString() + " " + ex.stack);
|
||||
}
|
||||
|
||||
return eventEmitter ? {
|
||||
|
@ -14,6 +14,7 @@ import * as net from "net";
|
||||
export interface ServerOptions {
|
||||
readonly workingDirectory: string;
|
||||
readonly dataDirectory: string;
|
||||
readonly builtInExtensionsDirectory: string;
|
||||
|
||||
forkProvider?(message: NewSessionMessage): cp.ChildProcess;
|
||||
}
|
||||
@ -35,7 +36,10 @@ export class Server {
|
||||
try {
|
||||
this.handleMessage(ClientMessage.deserializeBinary(data));
|
||||
} catch (ex) {
|
||||
logger.error("Failed to handle client message", field("length", data.byteLength), field("exception", ex));
|
||||
logger.error("Failed to handle client message", field("length", data.byteLength), field("exception", {
|
||||
message: ex.message,
|
||||
stack: ex.stack,
|
||||
}));
|
||||
}
|
||||
});
|
||||
connection.onClose(() => {
|
||||
@ -80,6 +84,7 @@ export class Server {
|
||||
const initMsg = new WorkingInitMessage();
|
||||
initMsg.setDataDirectory(options.dataDirectory);
|
||||
initMsg.setWorkingDirectory(options.workingDirectory);
|
||||
initMsg.setBuiltinExtensionsDir(options.builtInExtensionsDirectory);
|
||||
initMsg.setHomeDirectory(os.homedir());
|
||||
initMsg.setTmpDirectory(os.tmpdir());
|
||||
const platform = os.platform();
|
||||
@ -98,8 +103,8 @@ export class Server {
|
||||
throw new Error(`unrecognized platform "${platform}"`);
|
||||
}
|
||||
initMsg.setOperatingSystem(operatingSystem);
|
||||
if (process.env.SHELL) {
|
||||
initMsg.setShell(process.env.SHELL);
|
||||
if (global.process.env.SHELL) {
|
||||
initMsg.setShell(global.process.env.SHELL);
|
||||
}
|
||||
const srvMsg = new ServerMessage();
|
||||
srvMsg.setInit(initMsg);
|
||||
|
@ -63,4 +63,5 @@ message WorkingInitMessage {
|
||||
}
|
||||
OperatingSystem operating_system = 5;
|
||||
string shell = 6;
|
||||
string builtin_extensions_dir = 7;
|
||||
}
|
||||
|
4
packages/protocol/src/proto/client_pb.d.ts
vendored
4
packages/protocol/src/proto/client_pb.d.ts
vendored
@ -270,6 +270,9 @@ export class WorkingInitMessage extends jspb.Message {
|
||||
getShell(): string;
|
||||
setShell(value: string): void;
|
||||
|
||||
getBuiltinExtensionsDir(): string;
|
||||
setBuiltinExtensionsDir(value: string): void;
|
||||
|
||||
serializeBinary(): Uint8Array;
|
||||
toObject(includeInstance?: boolean): WorkingInitMessage.AsObject;
|
||||
static toObject(includeInstance: boolean, msg: WorkingInitMessage): WorkingInitMessage.AsObject;
|
||||
@ -288,6 +291,7 @@ export namespace WorkingInitMessage {
|
||||
workingDirectory: string,
|
||||
operatingSystem: WorkingInitMessage.OperatingSystem,
|
||||
shell: string,
|
||||
builtinExtensionsDir: string,
|
||||
}
|
||||
|
||||
export enum OperatingSystem {
|
||||
|
@ -1684,7 +1684,8 @@ proto.WorkingInitMessage.toObject = function(includeInstance, msg) {
|
||||
dataDirectory: msg.getDataDirectory(),
|
||||
workingDirectory: msg.getWorkingDirectory(),
|
||||
operatingSystem: msg.getOperatingSystem(),
|
||||
shell: msg.getShell()
|
||||
shell: msg.getShell(),
|
||||
builtinExtensionsDir: msg.getBuiltinExtensionsDir()
|
||||
};
|
||||
|
||||
if (includeInstance) {
|
||||
@ -1745,6 +1746,10 @@ proto.WorkingInitMessage.deserializeBinaryFromReader = function(msg, reader) {
|
||||
var value = /** @type {string} */ (reader.readString());
|
||||
msg.setShell(value);
|
||||
break;
|
||||
case 7:
|
||||
var value = /** @type {string} */ (reader.readString());
|
||||
msg.setBuiltinExtensionsDir(value);
|
||||
break;
|
||||
default:
|
||||
reader.skipField();
|
||||
break;
|
||||
@ -1825,6 +1830,13 @@ proto.WorkingInitMessage.prototype.serializeBinaryToWriter = function (writer) {
|
||||
f
|
||||
);
|
||||
}
|
||||
f = this.getBuiltinExtensionsDir();
|
||||
if (f.length > 0) {
|
||||
writer.writeString(
|
||||
7,
|
||||
f
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -1927,6 +1939,21 @@ proto.WorkingInitMessage.prototype.setShell = function(value) {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* optional string builtin_extensions_dir = 7;
|
||||
* @return {string}
|
||||
*/
|
||||
proto.WorkingInitMessage.prototype.getBuiltinExtensionsDir = function() {
|
||||
return /** @type {string} */ (jspb.Message.getFieldProto3(this, 7, ""));
|
||||
};
|
||||
|
||||
|
||||
/** @param {string} value */
|
||||
proto.WorkingInitMessage.prototype.setBuiltinExtensionsDir = function(value) {
|
||||
jspb.Message.setField(this, 7, value);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @enum {number}
|
||||
*/
|
||||
|
@ -536,7 +536,7 @@ describe("fs", () => {
|
||||
});
|
||||
|
||||
describe("stat", () => {
|
||||
it("should stat", (done) => {
|
||||
it("should stat file", (done) => {
|
||||
fs.stat(testFile, (err, stats) => {
|
||||
expect(err).toBeUndefined();
|
||||
expect(stats.size).toBeGreaterThan(0);
|
||||
@ -546,6 +546,17 @@ describe("fs", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("should stat folder", (done) => {
|
||||
const dir = tmpFile();
|
||||
nativeFs.mkdirSync(dir);
|
||||
|
||||
fs.stat(dir, (err, stats) => {
|
||||
expect(err).toBeUndefined();
|
||||
expect(stats.isDirectory()).toBeTruthy();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it("should fail to stat", (done) => {
|
||||
fs.stat(path.join(__dirname, "no-exist"), (err, stats) => {
|
||||
expect(err).toBeDefined();
|
||||
|
@ -236,22 +236,22 @@ ms@2.0.0:
|
||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
|
||||
integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=
|
||||
|
||||
nan@2.10.0:
|
||||
version "2.10.0"
|
||||
resolved "https://registry.yarnpkg.com/nan/-/nan-2.10.0.tgz#96d0cd610ebd58d4b4de9cc0c6828cda99c7548f"
|
||||
integrity sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==
|
||||
nan@2.12.1:
|
||||
version "2.12.1"
|
||||
resolved "https://registry.yarnpkg.com/nan/-/nan-2.12.1.tgz#7b1aa193e9aa86057e3c7bbd0ac448e770925552"
|
||||
integrity sha512-JY7V6lRkStKcKTvHO5NVSQRv+RV+FIL5pvDoLiAtSL9pKlC5x9PKQcZDsq7m4FO4d57mkhC6Z+QhAh3Jdk5JFw==
|
||||
|
||||
negotiator@0.6.1:
|
||||
version "0.6.1"
|
||||
resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.1.tgz#2b327184e8992101177b28563fb5e7102acd0ca9"
|
||||
integrity sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=
|
||||
|
||||
node-pty@^0.8.0:
|
||||
version "0.8.0"
|
||||
resolved "https://registry.yarnpkg.com/node-pty/-/node-pty-0.8.0.tgz#08bccb633f49e2e3f7245eb56ea6b40f37ccd64f"
|
||||
integrity sha512-g5ggk3gN4gLrDmAllee5ScFyX3YzpOC/U8VJafha4pE7do0TIE1voiIxEbHSRUOPD1xYqmY+uHhOKAd3avbxGQ==
|
||||
node-pty@^0.8.1:
|
||||
version "0.8.1"
|
||||
resolved "https://registry.yarnpkg.com/node-pty/-/node-pty-0.8.1.tgz#94b457bec013e7a09b8d9141f63b0787fa25c23f"
|
||||
integrity sha512-j+/g0Q5dR+vkELclpJpz32HcS3O/3EdPSGPvDXJZVJQLCvgG0toEbfmymxAEyQyZEpaoKHAcoL+PvKM+4N9nlw==
|
||||
dependencies:
|
||||
nan "2.10.0"
|
||||
nan "2.12.1"
|
||||
|
||||
on-finished@~2.3.0:
|
||||
version "2.3.0"
|
||||
@ -364,6 +364,11 @@ ts-protoc-gen@^0.8.0:
|
||||
dependencies:
|
||||
google-protobuf "^3.6.1"
|
||||
|
||||
tslib@^1.9.3:
|
||||
version "1.9.3"
|
||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286"
|
||||
integrity sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==
|
||||
|
||||
type-is@~1.6.16:
|
||||
version "1.6.16"
|
||||
resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.16.tgz#f89ce341541c672b25ee7ae3c73dee3b2be50194"
|
||||
|
Reference in New Issue
Block a user