motion
Version:
motion - moving development forward
362 lines (271 loc) • 14.3 kB
JavaScript
exports.__esModule = true;
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
exports.scripts = scripts;
exports.afterBuild = afterBuild;
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
var _libHelpers = require('./lib/helpers');
var _libStreams = require('./lib/streams');
var _libFns = require('../lib/fns');
var _libUnicodeToChar = require('../lib/unicodeToChar');
var _libUnicodeToChar2 = _interopRequireDefault(_libUnicodeToChar);
var _index = require('./index');
var _libFindRequires = require('../lib/findRequires');
var _babel = require('./babel');
var _babel2 = _interopRequireDefault(_babel);
var _bridge = require('../bridge');
var _bridge2 = _interopRequireDefault(_bridge);
var _cache = require('../cache');
var _cache2 = _interopRequireDefault(_cache);
var _builder = require('../builder');
var _builder2 = _interopRequireDefault(_builder);
var _bundler = require('../bundler');
var _bundler2 = _interopRequireDefault(_bundler);
var _scanner = require('./scanner');
var _scanner2 = _interopRequireDefault(_scanner);
var _opts = require('../opts');
var _opts2 = _interopRequireDefault(_opts);
var serializeCache = _libFns._.debounce(_cache2['default'].serialize, 600);
var hasFinished = function hasFinished() {
return hasBuilt() && _opts2['default']('hasRunInitialInstall');
};
var hasBuilt = function hasBuilt() {
return _opts2['default']('hasRunInitialBuild');
};
var getAllImports = function getAllImports(src, imports) {
return [].concat(_libFindRequires.findBabelRuntimeRequires(src), imports);
};
var scanNow = function scanNow() {
return _opts2['default']('build') || _opts2['default']('watch') || !_opts2['default']('hasRunInitialBuild');
};
function scripts(_ref) {
var _ref$inFiles = _ref.inFiles;
var inFiles = _ref$inFiles === undefined ? [] : _ref$inFiles;
var userStream = _ref.userStream;
var State = {
curFile: null,
lastError: null,
lastSaved: {},
loaded: 0,
total: inFiles.length,
outsideSources: {}
};
var scripts = userStream || _libHelpers.gulp.src(_libHelpers.SCRIPTS_GLOB).pipe(_libHelpers.$['if'](!_libHelpers.isBuilding(), _libHelpers.$.watch(_libHelpers.SCRIPTS_GLOB, { readDelay: 1 }))).pipe(_libHelpers.$['if'](function (file) {
return file.event == 'unlink';
}, _libHelpers.$.ignore.exclude(true)));
return (_libHelpers.isBuilding() ? scripts : _libHelpers.$.merge(scripts, _libStreams.dirAddStream(_opts2['default']('appDir')), new _libStreams.SuperStream().getStream())).pipe(_libHelpers.$['if'](buildCheck, _libHelpers.$.ignore.exclude(true))).pipe(_libHelpers.$.log(reset)).pipe(_libHelpers.$.plumber(catchError)).pipe(_libHelpers.$.log(setLastFile)).pipe(_scanner2['default']('pre')).pipe(_libHelpers.$.sourcemaps.init()).pipe(_babel2['default'].file()).pipe(_libHelpers.$.log(processDependencies)).pipe(_libHelpers.$.log(sendOutsideChanged)) // right after motion
.pipe(_libHelpers.$['if'](!userStream, _libHelpers.$.rename({ extname: '.js' }))).pipe(_libHelpers.$['if'](function (file) {
return file.babel.isExported;
}, _libHelpers.$.multipipe(_libHelpers.$.log(removeNewlyInternal), _libHelpers.$.log(markFileSuccess), // before writing to preserve path
_libHelpers.gulp.dest(_opts2['default']('deps').internalDir), _libHelpers.$.log(_bundler2['default'].internals.bind(null, { force: true })), _libHelpers.$.log(buildDone), _libHelpers.$.ignore.exclude(true)))).pipe(_libHelpers.$.sourcemaps.write('.')).pipe(_libHelpers.$.log(markFileSuccess)).pipe(_libHelpers.$['if'](checkWriteable, _libHelpers.gulp.dest(_opts2['default']('outDir')))).pipe(_libHelpers.$.log(afterWrite))
// temporary bugfix because gulp doesnt work well with watch (pending gulp 4)
.pipe(_libHelpers.$.log()).pipe(_libHelpers.$.log()).pipe(_libHelpers.$.log()).pipe(_libHelpers.$.log()).pipe(_libHelpers.$.log()).pipe(_libHelpers.$.log()).pipe(_libHelpers.$.log()).pipe(_libHelpers.$.log()).pipe(_libHelpers.$.log()).pipe(_libHelpers.$.log()).pipe(_libHelpers.$.log()).pipe(_libHelpers.$.log()).pipe(_libHelpers.$.log()).pipe(_libHelpers.$.log()).pipe(_libHelpers.$.log()).pipe(_libHelpers.$.log()).pipe(_libHelpers.$.log()).pipe(_libHelpers.$.log()).pipe(_libHelpers.$.log()).pipe(_libHelpers.$.log()).pipe(_libHelpers.$.log()).pipe(_libHelpers.$.log()).pipe(_libHelpers.$.log()).pipe(_libHelpers.$.log()).pipe(_libHelpers.$.log()).pipe(_libHelpers.$.log()).pipe(_libHelpers.$.log()).pipe(_libHelpers.$.log()).pipe(_libHelpers.$.log()).pipe(_libHelpers.$.log()).pipe(_libHelpers.$.log()).pipe(_libHelpers.$.log()).pipe(_libHelpers.$.log()).pipe(_libHelpers.$.log()).pipe(_libHelpers.$.log()).pipe(_libHelpers.$.log()).pipe(_libHelpers.$.log()).pipe(_libHelpers.$.log()).pipe(_libHelpers.$.log()).pipe(_libHelpers.$.log()).pipe(_libHelpers.$.log()).pipe(_libHelpers.$.log()).pipe(_libHelpers.$.log()).pipe(_libHelpers.$.log()).pipe(_libHelpers.$.log()).pipe(_libHelpers.$.log()).pipe(_libHelpers.$.log()).pipe(_libHelpers.$.log()).pipe(_libHelpers.$.log()).pipe(_libHelpers.$.log()).pipe(_libHelpers.$.log()).pipe(_libHelpers.$.log()).pipe(_libHelpers.$.log()).pipe(_libHelpers.$.log()).pipe(_libHelpers.$.log()).pipe(_libHelpers.$.log()).pipe(_libHelpers.$.log()).pipe(_libHelpers.$.log()).pipe(_libHelpers.$.log()).pipe(_libHelpers.$.log()).pipe(_libHelpers.$.log()).pipe(_libHelpers.$.log()).pipe(_libHelpers.$.log()).pipe(_libHelpers.$.log()).pipe(_libHelpers.$.log()).pipe(_libHelpers.$.log()).pipe(_libHelpers.$.log()).pipe(_libHelpers.$.log()).pipe(_libHelpers.$.log()).pipe(_libHelpers.$.log()).pipe(_libHelpers.$.log()).pipe(_libHelpers.$.log()).pipe(_libHelpers.$.log()).pipe(_libHelpers.$.log()).pipe(_libHelpers.$.log()).pipe(_libHelpers.$.log()).pipe(_libHelpers.$.log()).pipe(_libHelpers.$.log()).pipe(_libHelpers.$.log()).pipe(_libHelpers.$.log());
function markDone(file) {
State.loaded++;
var done = State.loaded == State.total;
_libFns.log.gulp('markDone', State.total, '/', State.loaded, done);
// check if done, only run once
if (done && !_opts2['default']('hasRunInitialBuild')) {
_opts2['default'].set('finishingFirstBuild', true);
file.finishingFirstBuild = true;
}
}
// only do on first run
function buildCheck(file) {
// BUGFIX gulp sends deleted files through here, this filters them
if (!file.contents) return true;
// already done with first build
if (hasBuilt()) return false;
// hide behind cached flag for now
if (!_opts2['default']('cached')) {
markDone(file);
return false;
}
var prevFile = _cache2['default'].getPrevious(file.path);
if (!prevFile) return false;
var outMTime = undefined,
srcMTime = undefined;
// read srcfile
try {
srcMTime = _libFns.fs.statSync(file.path).mtime;
} catch (e) {
return false;
}
// read outfile
try {
var relPath = _libFns.path.relative(_opts2['default']('appDir'), file.path);
var outFile = prevFile.babel.isExported ? _libFns.path.join(_opts2['default']('deps').dir, 'internal', relPath) : _libFns.path.join(_opts2['default']('outDir'), relPath);
outMTime = _libFns.fs.statSync(outFile).mtime;
} catch (e) {
_libFns.log.gulp('buildCheck', 'out file removed');
markDone(file);
return false;
}
// final check
var goodBuild = +outMTime > +srcMTime;
var goodCache = prevFile.added > srcMTime;
if (!goodBuild || !goodCache) return false;
return finish(true);
function finish() {
var restored = arguments.length <= 0 || arguments[0] === undefined ? false : arguments[0];
markDone(file);
if (restored) {
_cache2['default'].restorePrevious(file.path);
_libHelpers.out.goodScript(file);
afterWrite(file);
}
return restored;
}
}
function reset(file) {
_libFns.emitter.emit('script:start', file);
State.lastError = false;
State.curFile = file;
file.startTime = Date.now();
file.message = { startTime: file.startTime };
}
function catchError(error) {
_libFns.log.gulp('catchError', error);
State.lastError = true;
_libHelpers.out.badFile(State.curFile);
error.timestamp = Date.now();
error.stack = _libUnicodeToChar2['default'](error.stack);
_libFns.logError(error, State.curFile);
_index.event.run('error', State.curFile, error);
_cache2['default'].addError(error.fileName || '', error);
if (error.fileName) error.file = _libFns.path.relative(_opts2['default']('appDir'), error.fileName);
_bridge2['default'].broadcast('compile:error', { error: error }, 'error');
markDone(State.curFile);
buildDone(State.curFile);
}
function setLastFile(file) {
if (_libHelpers.isBuilding()) return;
var name = file.path.replace(_opts2['default']('appDir'), '');
if (name.charAt(0) != '/') name = '/' + name;
_libFns.log.gulp(name);
// add to message
file.message = _extends({}, file.message, {
name: name,
path: file.path,
compiledAt: file.startTime
});
State.curFile = file;
}
// sets isInternal and willInstall
// for handling npm and bundling related things
function processDependencies(file) {
_cache2['default'].setFileInternal(file.path, file.babel.isExported);
var scan = function scan() {
_cache2['default'].setFileImports(file.path, file.babel.imports);
_bundler2['default'].scanFile(file.path);
};
// run scan
if (file.babel.isExported || scanNow()) scan();else _libFns.debounce('install:' + file.path, 2000, scan);
if (!_opts2['default']('build') || _opts2['default']('watch')) {
_libFns.debounce('removeOldImports', 3000, _bundler2['default'].uninstall);
// check will install
file.willInstall = _bundler2['default'].willInstall(file.babel.imports);
}
}
// detects if a file has changed not inside views for hot reloads correctness
function sendOutsideChanged(file) {
var src = file.contents.toString();
var meta = _cache2['default'].getFileMeta(file.path);
if (!meta) return;
var changed = true;
var viewLocs = Object.keys(meta).map(function (view) {
return meta[view].location;
});
if (viewLocs.length) {
(function () {
// slice out all code not in views
var outerSlice = function outerSlice(ls, start, end) {
return ls.slice(0, start).concat(ls.slice(end));
};
var outside = viewLocs.reduce(function (src, loc) {
return outerSlice(src, loc[0][0], loc[1][0] + 1);
}, src.split("\n")).join('');
var prevOutside = State.outsideSources[file.path];
changed = prevOutside !== outside;
State.outsideSources[file.path] = outside; // update
})();
}
if (_opts2['default']('hasRunInitialBuild')) _bridge2['default'].broadcast('file:outsideChange', { name: _cache2['default'].relative(file.path), changed: changed });
}
function checkWriteable(file) {
if (userStream || State.lastError) return false;
if (_libHelpers.isBuilding()) return true;
var isNew = !State.lastSaved[file.path] || file.startTime > State.lastSaved[file.path];
if (isNew) {
State.lastSaved[file.path] = file.startTime;
return true;
}
return false;
}
function afterWrite(file) {
if (_libHelpers.isSourceMap(file.path)) return;
buildDone(file);
// avoid during initial build
if (!hasFinished()) return;
if (file.babel.isExported) return;
// run stuff after each change on build --watch
doBuild();
if (!_cache2['default'].get(file.path)) return; // avoid ?? todo: figure out why this is necessary
if (State.lastError) return; // avoid if error
// dont broadcast script if installing/bundling
_libFns.log.gulp('bundler installing?', _bundler2['default'].isInstalling(), 'willInstall?', file.willInstall);
if (_bundler2['default'].isInstalling() || file.willInstall) return;
// ADD
_bridge2['default'].broadcast('script:add', file.message);
}
function buildDone(file) {
if (file.finishingFirstBuild) {
_opts2['default'].set('hasRunInitialBuild', true);
_libFns.log.gulp('buildDone!!'.green.bold);
waitingForFirstBuild.forEach(function (res) {
return res();
});
}
}
function doBuild() {
if (_opts2['default']('watch') && hasBuilt()) {
_builder2['default'].build();
return true;
}
}
function markFileSuccess(file) {
if (_libHelpers.isSourceMap(file.path)) return;
_libFns.emitter.emit('script:end', file);
_libHelpers.out.goodScript(file);
_libFns.log.gulp('DOWN', 'success'.green, 'internal?', file.babel.isExported);
if (file.babel.isExported) return;
// update cache error / state
_cache2['default'].update(file.path);
// write cache state to disk
if (_opts2['default']('hasRunInitialBuild')) serializeCache();
// message browser of compile success
_bridge2['default'].broadcast('compile:success', file.message, 'error');
// check if other errors left still in queue
var error = _cache2['default'].getLastError();
if (!error) return;
_libFns.log.gulp('cache last error', error);
_bridge2['default'].broadcast('compile:error', { error: error }, 'error');
}
// ok so we start a file
// its built into .motion/out
// we then add an export
// now we need to remove it from .motion/out
function removeNewlyInternal(file) {
// resolve path from .motion/.internal/deps/internals/xyz.js back to xyz.js
var filePath = _libFns.path.relative(_libFns.p(_opts2['default']('deps').dir, 'internal'), file.path);
// then resolve path to .motion/.internal/out/xyz.js
var outPath = _libFns.p(_opts2['default']('outDir'), filePath);
// log.gulp('remove newly internal', outPath)
_libFns.rm(outPath);
}
}
var waitingForFirstBuild = [];
function afterBuild() {
return new Promise(function (res, rej) {
if (hasFinished()) return res();else waitingForFirstBuild.push(res);
});
}