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

Prototype of symbol messages #3

Closed
wants to merge 28 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
883cc8e
Prototype of symbol messages
phated Mar 10, 2024
7051ab4
box drawing symbols and changes to see in diff
phated Mar 10, 2024
10f19b2
task start/stop/etc
phated Mar 10, 2024
d552e73
remove theme and requires
phated Mar 10, 2024
1bcefb6
linting
phated Mar 10, 2024
09bcae0
npm install messages
phated Mar 10, 2024
5b73bbd
using gulpfile
phated Mar 10, 2024
294bbfb
move description to messages
phated Mar 10, 2024
cb03b9a
chore!: Remove support for alpha versions of gulp 4 (#255)
phated Mar 10, 2024
c70ce34
chore: Move task list helper functions into the logTasks closure (#256)
phated Mar 10, 2024
77f42fe
remove alphas
phated Mar 10, 2024
5e1fda2
Merge remote-tracking branch 'origin/master' into phated/translations
phated Mar 10, 2024
a1831c6
remove chalk from root
phated Mar 10, 2024
4fc66f6
chore: Revert options & yargs parser changes (#257)
phated Mar 10, 2024
528a0d7
Merge remote-tracking branch 'origin/master' into phated/translations
phated Mar 10, 2024
6e5c790
fix some getMessage calls
phated Mar 10, 2024
36f05d5
fix: Ensure the logger is wired up before running liftoff (#258)
phated Mar 11, 2024
ed86da7
feat!: Upgrade to Liftoff v5 and avoid merging flags/config/env (#259)
phated Mar 17, 2024
ac44fe2
Merge remote-tracking branch 'origin/master' into phated/translations
phated Mar 17, 2024
1000066
load user messages and timestamps, integrate with liftoff 5
phated Mar 17, 2024
c1a8775
remove file re-added in merge
phated Mar 17, 2024
e51382d
remove timestamp logic in favor of util.inspect
phated Mar 17, 2024
2e6b0c5
original tests passing
phated Mar 17, 2024
6fd4796
todo for the messages package
phated Mar 17, 2024
b079083
move tildify into the default messages
phated Mar 17, 2024
69e7993
restore package.json
phated Mar 17, 2024
3bc91df
remove extra files
phated Mar 17, 2024
8b85be1
remove extra test step
phated Mar 17, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 0 additions & 6 deletions .github/workflows/dev.yml
Expand Up @@ -56,12 +56,6 @@ jobs:
# Run test without coverage because a behavior about esm is different with nyc or not
run: npm test

- name: Run tests with coloring
run: npx mocha test/lib/theme.js
env:
FORCE_COLOR: 2
CI: ""

coveralls:
needs: test
name: Finish up
Expand Down
11 changes: 5 additions & 6 deletions README.md
Expand Up @@ -101,22 +101,21 @@ The CLI adds `process.env.INIT_CWD` which is the original cwd it was launched fr

Configuration is supported through the use of a `.gulp.*` file (e.g. `.gulp.json`, `.gulp.yml`). You can find a list of supported languages at https://github.com/gulpjs/interpret.

Configuration from the home directory (`~`) and current working directory (`cwd`) are merged with `cwd` taking precedence.
A configuration file from the current working directory (`cwd`) or above are selected before a configuration file from the home directory (`~`).

Supported configurations properties:

| Property | Description |
|--------------------|-------------|
| description | Top-level description of the project/gulpfile (Replaces "Tasks for ~/path/of/gulpfile.js") |
| gulpfile | Set a default gulpfile |
| preload | An array of modules to preload before running the gulpfile. Any relative paths will be resolved against the `--cwd` directory (if you don't want that behavior, use absolute paths) |
| nodeFlags | An array of flags used to forcibly respawn the process upon startup. For example, if you always want your gulpfiles to run in node's harmony mode, you can set `--harmony` here |
| flags.continue | Continue execution of tasks upon failure by default. |
| flags.compactTasks | Reduce the output of task dependency tree by default. |
| flags.tasksDepth | Set default depth of task dependency tree. |
| flags.gulpfile | Set a default gulpfile |
| flags.silent | Silence logging by default |
| flags.series | Run tasks given on the CLI in series (the default is parallel) |
| flags.preload | An array of modules to preload before running the gulpfile. Any relative paths will be resolved against the `--cwd` directory (if you don't want that behavior, use absolute paths) |
| flags.nodeFlags | An array of flags used to forcibly respawn the process upon startup. For example, if you always want your gulpfiles to run in node's harmony mode, you can set `--harmony` here |
| log.msgs.* | Configure log messages. |
| log.theme.* | Configure log theme. |

## Flags

Expand Down
170 changes: 111 additions & 59 deletions index.js
Expand Up @@ -2,24 +2,28 @@

var fs = require('fs');
var path = require('path');

var log = require('gulplog');
var yargs = require('yargs');
var Liftoff = require('liftoff');
var interpret = require('interpret');
var v8flags = require('v8flags');
var findRange = require('semver-greatest-satisfied-range');

var exit = require('./lib/shared/exit');
var tildify = require('./lib/shared/tildify');

var arrayFind = require('./lib/shared/array-find');
var makeTitle = require('./lib/shared/make-title');
var parser = require('./lib/shared/options/parser');
var makeHelp = require('./lib/shared/options/make-help');
var cliOptions = require('./lib/shared/options/cli-options');
var completion = require('./lib/shared/completion');
var cliVersion = require('./package.json').version;
var toConsole = require('./lib/shared/log/to-console');
var msgs = require('./lib/shared/log/messages');
var mergeCliOpts = require('./lib/shared/config/cli-flags');
var buildTranslations = require('./lib/shared/translate');

var mergeProjectAndUserHomeConfigs = require('./lib/shared/config/merge-configs');
var overrideEnvByConfigAndCliOpts = require('./lib/shared/config/env-config');
// TODO: make into `@gulpjs/messages`
var messages = require('./messages');

// Get supported ranges
var ranges = fs.readdirSync(path.join(__dirname, '/lib/versioned/'));
Expand All @@ -31,46 +35,52 @@ process.env.INIT_CWD = process.cwd();
var cli = new Liftoff({
name: 'gulp',
processTitle: makeTitle('gulp', process.argv.slice(2)),
completions: completion,
extensions: interpret.jsVariants,
v8flags: v8flags,
configFiles: {
project: [
{
name: '.gulp',
path: '.',
extensions: interpret.extensions,
findUp: true,
},
],
userHome: [
{
name: '.gulp',
path: '~',
extensions: interpret.extensions,
},
],
},
configFiles: [
{
name: '.gulp',
path: '.',
extensions: interpret.extensions,
findUp: true,
},
{
name: '.gulp',
path: '~',
extensions: interpret.extensions,
},
],
});

var opts = {};
var optsErr;
try {
opts = parser.argv;
} catch (e) {
optsErr = e;
}
var parser = yargs
.help(false)
.version(false)
.detectLocale(false)
.showHelpOnFail(false)
.exitProcess(false)
.fail(onFail)
.options(cliOptions);

var opts = parser.parse();

// Set up event listeners for logging temporarily.
// TODO: Rework console logging before we can set up proper config
// Possibly by batching messages in gulplog until listeners are attached
var cleanupListeners = toConsole(log, opts, buildTranslations());

cli.on('preload:before', function(name) {
log.info(msgs.info.preloadBefore, name);
log.info(messages.PRELOAD_BEFORE, name);
});

cli.on('preload:success', function(name) {
log.info(msgs.info.preloadSuccess, name);
log.info(messages.PRELOAD_SUCCESS, name);
});

cli.on('preload:failure', function(name, error) {
log.warn(msgs.warn.preloadFailure, name, Boolean(error), error.toString());
log.warn(messages.PRELOAD_FAILURE, name);
if (error) {
log.warn(messages.PRELOAD_ERROR, error);
}
});

cli.on('loader:success', function(name) {
Expand All @@ -79,61 +89,95 @@ cli.on('loader:success', function(name) {
// However, we don't want to show the mjs-stub loader in the logs
/* istanbul ignore else */
if (path.basename(name, '.js') !== 'mjs-stub') {
log.info(msgs.info.loaderSuccess, name);
log.info(messages.LOADER_SUCCESS, name);
}
});

cli.on('loader:failure', function(name, error) {
log.warn(msgs.warn.loaderFailure, name, Boolean(error), error.toString());
log.warn(messages.LOADER_FAILURE, name);
if (error) {
log.warn(messages.LOADER_ERROR, error);
}
});

cli.on('respawn', function(flags, child) {
log.info(msgs.info.respawn, flags.join(', '), child.pid);
log.info(messages.NODE_FLAGS, flags);
log.info(messages.RESPAWNED, child.pid);
});

function run() {
cli.prepare({
cwd: opts.cwd,
configPath: opts.gulpfile,
preload: opts.preload,
completion: opts.completion,
}, onPrepare);
}

module.exports = run;

function isDefined(cfg) {
return cfg != null;
}

function onFail(message, error) {
// Run Liftoff#prepare to get the env. Primarily to load themes.
cli.prepare({}, function (env) {
// We only use the first config found, which is a departure from
// the previous implementation that merged with the home
var cfg = arrayFind(env.config, isDefined);
var translate = buildTranslations(cfg);

var errorMsg = translate.message(messages.ARGV_ERROR, { message: message, error: error });
if (errorMsg) {
console.error(errorMsg);
}

makeHelp(parser, translate).showHelp(console.error);
exit(1);
});
}

function onPrepare(env) {
var cfg = mergeProjectAndUserHomeConfigs(env);
env = overrideEnvByConfigAndCliOpts(env, cfg, opts);
// We only use the first config found, which is a departure from
// the previous implementation that merged with the home
var cfg = arrayFind(env.config, isDefined);
var flags = mergeCliOpts(opts, cfg);

// Remove the previous listeners since we have appropriate config now
cleanupListeners();

var translate = buildTranslations(cfg);

// Set up event listeners for logging again after configuring.
toConsole(log, env.config.flags);
toConsole(log, flags, translate);

cli.execute(env, env.nodeFlags, onExecute);
cli.execute(env, cfg.nodeFlags, function (env) {
onExecute(env, flags, translate);
});
}

// The actual logic
function onExecute(env) {
function onExecute(env, flags, translate) {
// Moved the completion logic outside of Liftoff since we need to include translations
if (flags.completion) {
return completion(flags.completion, translate);
}

// This translates the --continue flag in gulp
// To the settle env variable for undertaker
// We use the process.env so the user's gulpfile
// Can know about the flag
if (env.config.flags.continue) {
if (flags.continue) {
process.env.UNDERTAKER_SETTLE = 'true';
}

if (optsErr) {
log.error(msgs.error.failToParseCliOpts, optsErr.message);
makeHelp(parser).showHelp(console.error);
exit(1);
}
if (env.config.flags.help) {
makeHelp(parser).showHelp(console.log);
if (flags.help) {
makeHelp(parser, translate).showHelp(console.log);
exit(0);
}

// Anything that needs to print outside of the logging mechanism should use console.log
if (env.config.flags.version) {
if (flags.version) {
console.log('CLI version:', cliVersion);
console.log('Local version:', env.modulePackage.version || 'Unknown');
exit(0);
Expand All @@ -145,37 +189,45 @@ function onExecute(env) {
&& !fs.existsSync(path.join(env.cwd, 'node_modules'));

var hasYarn = fs.existsSync(path.join(env.cwd, 'yarn.lock'));
var hasNpm = !hasYarn;

if (missingNodeModules) {
log.error(msgs.error.nodeModulesNotFound, tildify(env.cwd), hasYarn, hasNpm);
log.error(messages.MISSING_NODE_MODULES, { cwd: env.cwd });
if (hasYarn) {
log.error(messages.YARN_INSTALL)
} else {
log.error(messages.NPM_INSTALL)
}
} else {
log.error(msgs.error.gulpNotFound, tildify(env.cwd), hasYarn, hasNpm);
log.error(messages.MISSING_GULP, { cwd: env.cwd });
if (hasYarn) {
log.error(messages.YARN_INSTALL_GULP);
} else {
log.error(messages.NPM_INSTALL_GULP);
}
}
exit(1);
}

if (!env.configPath) {
log.error(msgs.error.gulpfileNotFound);
log.error(messages.GULPFILE_NOT_FOUND);
exit(1);
}

// Chdir before requiring gulpfile to make sure
// we let them chdir as needed
if (process.cwd() !== env.cwd) {
process.chdir(env.cwd);
log.info(msgs.info.cwdChanged, tildify(env.cwd));
log.info(messages.CWD_CHANGED, { cwd: env.cwd });
}

// Find the correct CLI version to run
var range = findRange(env.modulePackage.version, ranges);

if (!range) {
log.error(msgs.error.badGulpVersion, env.modulePackage.version);
log.error(messages.UNSUPPORTED_GULP_VERSION, env.modulePackage.version);
exit(1);
}

// Load and execute the CLI version
var versionedDir = path.join(__dirname, '/lib/versioned/', range, '/');
require(versionedDir)(env);
require(versionedDir)(env, flags, translate);
}
19 changes: 19 additions & 0 deletions lib/shared/array-find.js
@@ -0,0 +1,19 @@
'use strict';

function arrayFind(arr, fn) {
if (!Array.isArray(arr)) {
return;
}

var idx = 0;
while (idx < arr.length) {
var result = fn(arr[idx]);
if (result) {
// TODO: This is wrong in Liftoff
return arr[idx];
}
idx++;
}
}

module.exports = arrayFind;
11 changes: 5 additions & 6 deletions lib/shared/completion.js
Expand Up @@ -2,21 +2,20 @@

var fs = require('fs');
var path = require('path');
var format = require('theming-log').format;

var theme = require('./log/theme');
var msgs = require('./log/messages');
// TODO: make into `@gulpjs/messages`
var messages = require('../../messages');

module.exports = function(name) {
module.exports = function(name, translate) {
if (typeof name !== 'string') {
throw new Error(format(theme, msgs.error.noCompletionType));
throw new Error(translate.message(messages.COMPLETION_TYPE_MISSING));
}
var file = path.join(__dirname, '../../completion', name);
try {
console.log(fs.readFileSync(file, 'utf8'));
process.exit(0);
} catch (err) {
console.log(format(theme, msgs.error.unknownCompletionType, name));
console.log(translate.message(messages.COMPLETION_TYPE_UNKNOWN, { name: name }));
process.exit(5);
}
};