Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Npm package #598

Merged
merged 27 commits into from
Nov 30, 2016
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
469bea3
npm-ready package.json
joshuafcole Nov 17, 2016
ce86bb9
Merge branch 'feature/npm-package' into app-loading
joshuafcole Nov 18, 2016
cd7db0b
merge
joshuafcole Nov 18, 2016
5313990
location-independent Eve binary WIP
joshuafcole Nov 22, 2016
2fa8531
Pull config out into module, add npmignore, update build phase for pa…
joshuafcole Nov 23, 2016
db9d0ad
Remove workspaces rewrite from server (doesnt work when installed -g)
joshuafcole Nov 24, 2016
074db56
Update readme
cmontella Nov 24, 2016
6cf8fb5
Fix package-workspaces script to include eve src workspace
joshuafcole Nov 24, 2016
7d4429f
Add eveSource.find to resolve a workspace-relative URL to a file
joshuafcole Nov 24, 2016
1b657c1
Fix fully local-initialization
joshuafcole Nov 24, 2016
d521b45
Merge branch 'npm-package' of github.com:/witheve/eve into npm-package
joshuafcole Nov 24, 2016
8b8b96b
Add fixme about file arg in eve binary
joshuafcole Nov 24, 2016
76c29fd
Fix crash when trying to load nonexistent document
joshuafcole Nov 24, 2016
1d34dfb
Fix crash when loading nonexistent document, add getRelativePath, don…
joshuafcole Nov 24, 2016
03ab7c3
Only attempt to load sane documents
joshuafcole Nov 24, 2016
0679a34
Dont explode when initializing without code
joshuafcole Nov 24, 2016
58463ac
Fix editor workspace/document loading in external projects
joshuafcole Nov 24, 2016
bd67f07
Fix port flag not overriding ENV and file argument following a boolea…
joshuafcole Nov 28, 2016
2d08d27
Remove console logs
joshuafcole Nov 28, 2016
e3aaa1a
Remove vestigial code
joshuafcole Nov 28, 2016
a24ecae
Standardize variable names
joshuafcole Nov 28, 2016
10f0dc1
Move document saving into eveSource and separate runtimeOwner and con…
joshuafcole Nov 29, 2016
c24d114
Fix loading quickstart on global install + local control when running…
joshuafcole Nov 29, 2016
deb8277
Fix broken path logic
joshuafcole Nov 29, 2016
0b00981
Dont explode on non-existent documents
joshuafcole Nov 29, 2016
22d763e
Do stricter url normalization
joshuafcole Nov 29, 2016
6b24a5d
Recombobulate eve document resolution
joshuafcole Nov 29, 2016
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 14 additions & 6 deletions bin/eve.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@ var fs = require("fs");
var minimist = require("minimist");

var config = require("../build/src/config");
var Owner = config.Owner;
var server = require("../build/src/runtime/server");

const argv = minimist(process.argv.slice(2));
const argv = minimist(process.argv.slice(2), {boolean: ["server", "editor"]});

// Since our current development pattern uses npm as its package repository, we treat the nearest ancestor directory with a package.json (inclusive) as the directory's "root".
function findRoot(root) {
Expand All @@ -23,10 +24,11 @@ function findRoot(root) {
}


var browser = !argv["server"];
var port = process.env.PORT || argv["port"] || 8080;
var filepath = argv["_"][0]; // @FIXME: This should really be the first positional argument, not the first of any argument. (undefined if a user flags first).
var port = argv["port"] || process.env.PORT || 8080;
var runtimeOwner = argv["server"] ? Owner.server : Owner.client;
var controlOwner = argv["localControl"] ? Owner.client : Owner.server;
var editor = argv["editor"] || false;
var filepath = argv["_"][0];
var internal = false;

var root = findRoot(process.cwd());
Expand All @@ -36,18 +38,24 @@ var eveRoot = findRoot(__dirname);
// If we're executing within the eve module/repo, we're running internally and should expose our examples, src, etc.
// This should be handled down the road by some sort of a manifest in conjunction with the `root` rather than hardcoding.
if(root === eveRoot) internal = true;
else if(!root) {
internal = true;
// We shouldn't (and when globally installed, *can't*) taint the internal examples when running as an installed binary.
// @TODO: In the future we should have a more flexible solution that can copy out the examples into your current workspace when edited.
controlOwner = Owner.client;
}


// If we're not given an explicit filepath to run, assume the user wanted the editor (rather than a blank page).
// Similarly, if we're running internally, send the user over to the quickstart, since they're likely testing the waters.
if(!filepath) {
editor = true;
if(internal) filepath = "examples/quickstart.eve";
if(internal) filepath = eveRoot + "/" + "examples/quickstart.eve";
} else {
filepath = path.resolve(filepath);
}

var opts = {internal: internal, browser: browser, editor: editor, port: port, path: filepath, internal: internal, root: root, eveRoot: eveRoot};
var opts = {internal: internal, runtimeOwner: runtimeOwner, controlOwner: controlOwner, editor: editor, port: port, path: filepath, internal: internal, root: root, eveRoot: eveRoot};
config.init(opts);

server.run(opts);
2 changes: 1 addition & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
SystemJS.config({
baseURL: "build/src",
defaultJSExtensions: true,
map: {fs: "@empty", path: "@empty", glob: "@empty"},
map: {fs: "@empty", path: "@empty", glob: "@empty", mkdirp: "@empty"},
meta: {"build/src/codemirror.js": { format: "cjs" }}
});

Expand Down
2 changes: 0 additions & 2 deletions scripts/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,6 @@ export function build(callback:() => void) {
for(let dep of deps) {
dep = path.resolve(dep);
let base = dep.split("/").pop();
console.log("COPYING", dep);
console.log("NM", fs.readdirSync("node_modules"));
copy(dep, "build/src/" + base, tracker.track("copy node module files"));
}

Expand Down
20 changes: 9 additions & 11 deletions src/client.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {clone, debounce, uuid, sortComparator} from "./util";
import {Owner} from "./config";
import {sentInputValues, activeIds, renderRecords, renderEve} from "./renderer"
import {IDE} from "./ide";
import * as browser from "./runtime/browser";
Expand Down Expand Up @@ -202,7 +203,7 @@ export class EveClient {
this.localControl = true;
this.localEve = true;
if(!this.ide) {
this._initProgram({local: true, withIDE: true, path: (window.location.hash || "").slice(1) || "/examples/quickstart.eve"});
this._initProgram({runtimeOwner: Owner.client, controlOwner: Owner.client, withIDE: true, path: (window.location.hash || "").slice(1) || "/examples/quickstart.eve"});
} else if(this.showIDE) {
this.ide.injectNotice("error", "Unexpectedly disconnected from the server. Please refresh the page.");
} else {
Expand Down Expand Up @@ -268,9 +269,10 @@ export class EveClient {
}

_initProgram(data) {
this.localEve = data.local;
this.localEve = data.runtimeOwner === Owner.client;
this.localControl = data.controlOwner === Owner.client;
this.showIDE = data.withIDE;
if(data.local) {
if(this.localEve) {
browser.init(data.code);
}
if(this.showIDE) {
Expand All @@ -282,7 +284,7 @@ export class EveClient {
}

this.ide = new IDE();
this.ide.local = data.local;
this.ide.local = this.localControl;
initIDE(this);
this.ide.render();
if(data.path && data.path.length > 2) {
Expand Down Expand Up @@ -437,10 +439,6 @@ function initIDE(client:EveClient) {
client.send({scope: "root", type: "parse", code})
client.send({type: "eval", persist: false});
let url = `${location.pathname}#${documentId}`;
// @FIXME: I think this is vestigial, but need to confirm this.
// if(documentId.indexOf("/examples/") === -1) {
// url = `${location.pathname}#/examples/${documentId}`;
// }
history.pushState({}, "", url + location.search);
analyticsEvent("load-document", documentId);
}
Expand All @@ -464,10 +462,10 @@ function changeDocument() {
let ide = client.ide;
// @FIXME: This is not right in the non-internal case.
let docId = "/examples/quickstart.eve";
let path = "/" + location.hash.split('?')[0].split("#/")[1];
if(path) {
let path = location.hash && location.hash.split('?')[0].split("#/")[1];
if(path && path.length > 2) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why > 2?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In order to be remotely valid it needs to contain at least a character and a slash. Honestly it should be 3, since all files must at least be /

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

probably worth putting a comment in or maybe a regex or something?

if(path[path.length - 1] === "/") path = path.slice(0, -1);
docId = path;
docId = "/" + path;
}
if(!docId) return;
if(docId === ide.documentId) return;
Expand Down
4 changes: 3 additions & 1 deletion src/config.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
export interface Config {path?:string, browser?: boolean, port?:number, editor?: boolean, root?: string, eveRoot?: string, internal?: boolean}
export enum Owner {client, server};

export interface Config {path?:string, runtimeOwner?: Owner, controlOwner?: Owner, port?:number, editor?: boolean, root?: string, eveRoot?: string, internal?: boolean}

export var config:Config = {};

Expand Down
5 changes: 4 additions & 1 deletion src/ide.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,10 @@ class Navigator {
headings.sort(compareSpans);

let root:TreeNode = this.nodes[id];
if(!root) throw new Error("Cannot load non-existent document.");
if(!root) {
console.error("Cannot load non-existent document.");
return;
}
root.open = true;
root.children = undefined;

Expand Down
92 changes: 81 additions & 11 deletions src/runtime/eveSource.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,26 @@
export let workspaces:{[name:string]: string} = {};

//---------------------------------------------------------
// Public
//---------------------------------------------------------

export function add(name: string, directory: string) {
// If we're running on a windows server, normalize slashes
if(typeof window === undefined) {
if(process.platform.search(/^win/)) {
directory = directory.replace("\\", "/");
}
}

if(directory[directory.length - 1] !== "/") directory += "/";

if(workspaces[name] && workspaces[name] !== directory)
throw new Error(`Unable to link pre-existing workspace '$[name}' to '${directory}' (currently '${workspaces[name]}')`);

workspaces[name] = directory;
}

/** Given an explicit workspace, return the contents of the file. */
export function get(file:string, workspace = "eve"):string|undefined {
if(!workspaces[workspace]) {
console.error(`Unable to get '${file}' from unregistered workspace '${workspace}'`);
Expand All @@ -16,7 +30,38 @@ export function get(file:string, workspace = "eve"):string|undefined {
return fetchFile(file, workspace);
}

/** Using the inferred workspace from the file path, return the contents of the file. */
export function find(file:string):string|undefined {
let workspace = getWorkspaceFromPath(file);
if(!workspace) return;

return get(file, workspace);
}

/** Given an explicit workspace, update the contents of the file. */
export function set(file:string, content:string, workspace = "eve") {
if(!workspaces[workspace]) {
console.error(`Unable to set '${file}' from unregistered workspace '${workspace}'`);
return;
}

saveFile(file, content, workspace);
}

/** Using the inferred workspace from the file path, update the contents of the file. */
export function save(file:string, content:string) {
let workspace = getWorkspaceFromPath(file);
if(!workspace) return;

return set(file, content, workspace);
}

//---------------------------------------------------------
// Utilities
//---------------------------------------------------------


export function getWorkspaceFromPath(file:string):string|undefined {
var parts = file.split("/");
var basename = parts.pop();
var workspace = parts[1];
Expand All @@ -25,12 +70,12 @@ export function find(file:string):string|undefined {
console.error(`Unable to get '${file}' from unregistered workspace '${workspace}'`);
}

return get(file, workspace);
return workspace;
}

export function getRelativePath(file:string, workspace:string) {
let root = workspaces[workspace];
if(!root) {
export function getRelativePath(file:string, workspace:string):string|undefined {
let directory = workspaces[workspace];
if(!directory) {
console.error(`Unable to get relative path for '${file}' in unregistered workspace '${workspace}'`);
return;
}
Expand All @@ -39,16 +84,35 @@ export function getRelativePath(file:string, workspace:string) {
file = file.slice(2);
}

if(file.indexOf(root) === 0) {
file = file.slice(root.length + 1);
if(file.indexOf(directory) === 0) {
file = file.slice(directory.length);
}
return "/" + workspace + "/" + file;
}

export function getAbsolutePath(file:string, workspace:string) {
let directory = workspaces[workspace];
if(file.indexOf(directory) === 0) return file;

if(file.indexOf("/" + workspace + "/") === 0) file = file.slice(workspace.length + 2);
return directory + file;
}

//---------------------------------------------------------
// Server/Client Implementations
//---------------------------------------------------------

var saveFile = function(file:string, content:string, workspace:string) {
let cache = global["_workspaceCache"][workspace];
cache = global["_workspaceCache"][workspace] = {};
file = getRelativePath(file, workspace);
cache[file] = content;
}

// If we're running on the client, we use the global _workspaceCache, created in the build phase or served by the server.
var fetchFile = function(file:string, workspace:string):string|undefined {
let cache = global["_workspaceCache"][workspace];
if(file.indexOf("/" + workspace) !== 0) file = "/" + workspace + "/" + file;
file = getRelativePath(file, workspace);
return cache && cache[file];
}

Expand All @@ -61,11 +125,17 @@ if(typeof window === "undefined") {
let glob = require("glob");
let fs = require("fs");
let path = require("path");
let mkdirp = require("mkdirp");

var getAbsolutePath = function(file:string, workspace:string) {
let directory = workspaces[workspace];
if(file.indexOf("/" + workspace) === 0) file = file.slice(workspace.length + 1);
return path.join(directory, file).replace("/", path.sep);
saveFile = function(file:string, content:string, workspace:string) {
try {
let filepath = getAbsolutePath(file, workspace);
let dirname = path.dirname(filepath);
mkdirp.sync(dirname);
fs.writeFileSync(filepath, content);
} catch(err) {
console.warn(`Unable to save file '${file}' in '${workspace}' containing:\n${content}`);
}
}

fetchFile = function(file:string, workspace:string):string|undefined {
Expand Down
Loading