@tangelo/tangelo-configuration-toolkit
Version:
Tangelo Configuration Toolkit is a command-line toolkit which offers support for developing a Tangelo configuration.
147 lines (115 loc) • 5.83 kB
JavaScript
global._appStartTime = new Date();
require('./src/lib/set-string-getters.js');
require('./src/lib/set-global-functions.js');
const {execSync} = require('child_process');
const findUp = require('find-up');
const fs = require('fs-extra');
const homedir = require('os').homedir();
const path = require('path');
const execGitCommand = require('./src/lib/exec-git-command');
const memoize = require('./src/lib/memoize');
global._package = require('./package.json');
global._devmode = !__dirname.includes('node_modules');
global._paths = {
app: __dirname,
apphome: path.join(homedir, '.tct'),
repo: findUp.sync(dir => fs.existsSync(path.join(dir, '.git')) && dir, {type: 'directory'}) || '',
tdi: 'tangelo-default-implementation',
gitremote: 'git@bitbucket.org:tangelosoftware'
};
_paths.appdata = path.join(_paths.apphome, 'appdata.json');
_paths.appconfig = path.join(_paths.apphome, 'appconfig.json');
_paths.apply = process.cwd().replace(_paths.repo, '').slice(1);
global._appdata = fs.readJsonSync(_paths.appdata, {throws: false}) || {};
_appdata._update = data => Object.assign(_appdata, data, {_changed: true});
if (!_appdata.npmPath) {
_appdata._update({npmPath: execSync('npm config get prefix', {encoding: 'UTF-8'}).replace(/\s$/, '')});
}
global._appconfig = { // default appconfig if file not found
'sharedConfigPath': path.join(homedir, 'Dropbox (Tangelo Software)/Product Distribution/tooling'),
'servers': [],
'defaultServer': 'tdpXX',
'defaultDatabase': 'tdpXX'
};
try {
global._appconfig = fs.readJsonSync(_paths.appconfig);
}
catch({code, message}) {
if (code === 'ENOENT') { // create appconfig json if not exists
fs.ensureDirSync(_paths.apphome);
fs.writeJsonSync(_paths.appconfig, global._appconfig, {spaces: 2});
_info(`${_paths.appconfig} was created`);
}
else _error('Could not load app-config: '+message);
}
global._repoconfig = require('./src/lib/get-repoconfig')(_paths.repo);
const filenameSC = _package.name.split('/').pop() + '-appconfig.json';
_appconfig.sharedConfigPath = path.resolve(_paths.appconfig, '..', _appconfig.sharedConfigPath || '', filenameSC);
_appconfig.shared = fs.readJsonSync(_appconfig.sharedConfigPath, {throws: false}) || {};
global._git = {
user () {
if (!_appdata.gitUser) _appdata._update({gitUser: execGitCommand(`config --get user.email`, _paths.repo)});
return _appdata.gitUser;
},
status: memoize(() => execGitCommand(`status -s`, _paths.repo)),
commitLocal: memoize(() => execGitCommand(`log -1 --format=%D;%H;%cd --date=iso-strict`, _paths.repo, ['branch', 'hash', 'date'])),
commitRemote: memoize(() => execGitCommand('log -1 --format=%cd --date=iso-strict origin/' + _git.commitLocal().branch, _paths.repo, ['date'])),
commitTdi: {
local: memoize(() => execGitCommand(`log -1 --format=%D;%H;%cd --date=iso-strict`, path.join(_paths.repo, _paths.tdi), ['tags', 'hash', 'date'])),
after: memoize(commitHash => execGitCommand(`merge-base --is-ancestor ${commitHash} ${_git.commitTdi.local().hash}`, path.join(_paths.repo, _paths.tdi), null, 0)),
fontoVersions: [ // latest commits first
{commitHash: 'e599766', regex: /^7\.1[45]\./},
{commitHash: '77b8ea9', regex: /^7\.14\./}, // 7.14.x
{commitHash: '8066c44', regex: /^7\.13\./}, // 7.13.x
{commitHash: 'a2b2d4e', regex: /^7\.12\./} // 7.12.x
],
hasUncommittedFiles: memoize(() => execGitCommand(`status --short`, path.join(_paths.repo, _paths.tdi)).length > 0),
},
hasUncommittedFiles: memoize(() => execGitCommand(`status --short`, _paths.repo).length > 0),
};
global._tdiSubmoduleExists = () => fs.existsSync(path.join(_paths.repo, _paths.tdi));
global._isPre42 = () => fs.existsSync(path.join(_paths.repo, _paths.tdi, 'create_new_project')); // folder changed in 4.2
global._isPre51 = () => !fs.existsSync(path.join(_paths.repo, _paths.tdi, 'src')); // folder changed in 5.1 (check new folder because old one could still exist after branch switch)
global._modulesTdi = {
absolutePathTdi: path.join(_paths.repo, _paths.tdi),
ensureDepsUpToDate(message) {
if (this.depsUpToDate) return;
try {
if (message) _info('Checking installed dependencies in submodule');
execSync('npm list', {cwd: this.absolutePathTdi, stdio: 'ignore'});
} catch (e) {
if (message) _info('Updating dependencies in submodule');
execSync('npm update', {cwd: this.absolutePathTdi, stdio: 'ignore'});
}
this.depsUpToDate = true;
},
require(module, {throws = true, message = true} = {}) {
if (path.extname(module) !== '.json') this.ensureDepsUpToDate();
if (message) _info(`Loading ${path.join(_paths.tdi, 'tct', module)}\n`);
try {
return require(path.join(this.absolutePathTdi, 'tct', module));
}
catch (e) {
if (throws) {
_debug(`${e}`);
_error('Module could not be loaded: ' + module);
}
else return undefined;
}
}
};
global._settingsTdi = memoize(() => Object.assign(_package.settingsTdiDefault, _modulesTdi.require('settings.json', {throws: false, message: false}) ?? {}));
global._filters = {
fontoSources: ['!**/node_modules/**', '!**/fonto/packages/**', '!**/fonto/packages_shared/**', '!**/fonto/platform/**']
};
process.on('beforeExit', () => {
_write(); // print empty line before and after update check
require('./src/lib/package-update-check')();
if (_appdata._changed) {
delete _appdata._update;
delete _appdata._changed;
fs.writeJsonSync(_paths.appdata, _appdata, {spaces: 2});
}
if (_devmode) _perf(_appStartTime); // output execution time in dev mode
});
require('./src/cli.js')();