bart-tile/install.js

192 lines
7.1 KiB
JavaScript

const prompt = require('prompt')
const replace = require('replace-in-file')
const fs = require('fs-extra');
var Promise = require('promise');
var path = require('path');
// Making the text input a bit legible.
prompt.colors = false
prompt.message = ""
// The text input takes a "result" object and passes it to one of two functions to do the logistics.
prompt.get([{
name: 'appName',
required: true,
description: "What's the name of your application? Lowercase and no spaces, please.",
message: "Lowercase and no spaces, please.",
conform: function(value) {
return /^[a-z0-9]+((\-[a-z0-9]+){1,})?$/g.test(value)
}
},
{
name: 'type',
required: true,
description: "Is your app just a tile, or a full application? (tile/full)",
message: "Please specify 'tile' or 'full'.",
conform: function(value) {
if ((value == "tile") || (value == "full")) return true
return false
}
},
{
name: 'pier',
required: true,
description: "Where is your Urbit pier's desk located? For example, /Users/dev/zod/home"
}], function (err, result) {
if (result.type == "tile") setupTile(result)
else if (result.type == "full") setupFull(result)
}
)
// Delete the 'full' app folder and rename the tile-only files.
const setupTile = function (result) {
deleteFolderRecursive('full')
let deHyphenatedName = result.appName.indexOf('-') > -1 ? result.appName.replace(/-/g, "") : result.appName
fs.renameSync('urbit/app/smol.hoon', 'urbit/app/' + deHyphenatedName + '.hoon')
// Make a copy of the name without hyphens for the JS naming.
let capitalisedAppName = deHyphenatedName.charAt(0).toUpperCase() + deHyphenatedName.slice(1)
let appNameOptions = {
files: ['gulpfile.js', 'urbit/app/' + deHyphenatedName + '.hoon'],
from: /%APPNAME%/g,
to: deHyphenatedName
}
let appNamewithCapitals = {
files: 'tile/tile.js',
from: [/%APPNAME%Tile/g, /%APPNAME%/g],
to: [deHyphenatedName + "Tile", capitalisedAppName]
}
let urbitPierOptions = {
files: '.urbitrc',
from: "%URBITPIER%",
to: result.pier
}
replace(appNameOptions).then(changedFiles => console.log(changedFiles)).catch(err => console.error(err))
replace(appNamewithCapitals).then(changedFiles => console.log(changedFiles)).catch(err => console.error(err))
replace(urbitPierOptions).then(changedFiles => console.log(changedFiles)).catch(err => console.error(err))
console.log("All done! Happy hacking.")
}
// Delete the tile-specific files and move the full application to root. Rename everything as necessary.
const deleteFolderRecursive = function (path) {
if (fs.existsSync(path)) {
fs.readdirSync(path).forEach(function (file, index) {
var curPath = path + "/" + file;
if (fs.lstatSync(curPath).isDirectory()) {
deleteFolderRecursive(curPath);
} else {
fs.unlinkSync(curPath);
}
});
fs.rmdirSync(path);
}
};
var promiseAllWait = function (promises) {
// this is the same as Promise.all(), except that it will wait for all promises to fulfill before rejecting
var all_promises = [];
for (var i_promise = 0; i_promise < promises.length; i_promise++) {
all_promises.push(
promises[i_promise]
.then(function (res) {
return { res: res };
}).catch(function (err) {
return { err: err };
})
);
}
return Promise.all(all_promises)
.then(function (results) {
return new Promise(function (resolve, reject) {
var is_failure = false;
var i_result;
for (i_result = 0; i_result < results.length; i_result++) {
if (results[i_result].err) {
is_failure = true;
break;
} else {
results[i_result] = results[i_result].res;
}
}
if (is_failure) {
reject(results[i_result].err);
} else {
resolve(results);
}
});
});
};
var movePromiser = function (from, to, records) {
return fs.move(from, to)
.then(function () {
records.push({ from: from, to: to });
});
};
var moveDir = function (from_dir, to_dir, callback) {
return fs.readdir(from_dir)
.then(function (children) {
return fs.ensureDir(to_dir)
.then(function () {
var move_promises = [];
var moved_records = [];
var child;
for (var i_child = 0; i_child < children.length; i_child++) {
child = children[i_child];
move_promises.push(movePromiser(
path.join(from_dir, child),
path.join(to_dir, child),
moved_records
));
}
return promiseAllWait(move_promises)
.catch(function (err) {
var undo_move_promises = [];
for (var i_moved_record = 0; i_moved_record < moved_records.length; i_moved_record++) {
undo_move_promises.push(fs.move(moved_records[i_moved_record].to, moved_records[i_moved_record].from));
}
return promiseAllWait(undo_move_promises)
.then(function () {
throw err;
});
});
}).then(function () {
return fs.rmdir(from_dir);
});
}).then(callback);
};
const setupFull = function (result) {
deleteFolderRecursive('tile')
deleteFolderRecursive('urbit')
fs.unlinkSync('gulpfile.js')
let deHyphenatedName = result.appName.indexOf('-') > -1 ? result.appName.replace(/-/g, "") : result.appName
moveDir('full', './', function() {
fs.renameSync('urbit/app/smol.hoon', 'urbit/app/' + deHyphenatedName + '.hoon')
fs.renameSync('urbit/app/smol/', 'urbit/app/' + deHyphenatedName)
let urbitPierOptions = {
files: '.urbitrc',
from: "%URBITPIER%",
to: result.pier
}
replace(urbitPierOptions).then(changedFiles => console.log(changedFiles)).catch(err => console.error(err))
let appNameOptions = {
files: ['gulpfile.js', 'urbit/app/' + deHyphenatedName + '.hoon', 'tile/tile.js',
'src/js/api.js', 'src/js/subscription.js', 'src/js/components/root.js',
'src/js/reducers/config.js', 'urbit/app/' + deHyphenatedName + '/index.html', 'src/js/components/lib/icons/icon-home.js'
],
from: /%APPNAME%/g,
to: deHyphenatedName
}
replace(appNameOptions).then(changedFiles => console.log(changedFiles)).catch(err => console.error(err))
})
}