Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 2 additions & 1 deletion .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"no-console": "off",
"import/no-extraneous-dependencies": "off",
"prefer-object-spread": "off",
"no-multiple-empty-lines": "off"
"no-multiple-empty-lines": "off",
"import/extensions": "off"
}
}
14 changes: 9 additions & 5 deletions doc/dev-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ At minimum, include `type` and `describe` properties for all options help popula
In the command's builder, apply options with `.option()`:

```javascript
command: 'hello',
command: 'hello',
builder: (yargs) => {
yargs
.option('name', {
Expand Down Expand Up @@ -251,7 +251,7 @@ To accept standard input (stdin) within a command, apply one of the CLI's stdin

Each of the CLI's stdin middleware accept a key and return the middleware function for use by Yargs. When the middleware is invoked, stdin will be parsed and, if available, assigned to the specified option key. From within the command, simply access the value as you would any other option.

For example, the following will assign `stdin`, parsed as an string, to the `name` option. For consistency, include "(stdin)" in your option's description to surface this consistently in the CLI's generated documentation.
For example, the following will assign `stdin`, parsed as an string, to the `name` option. For consistency, include "(stdin)" in your option's description to surface this consistently in the CLI's generated documentation.

```javascript
// Lazy load to improve startup time
Expand Down Expand Up @@ -384,15 +384,19 @@ Yargs will surface descriptions for each command in the `mod` directory with the

Logging is instrumented with the [debug](https://www.npmjs.com/package/debug) utility. All logs within the CLI pass through `lib/cli/logger.js`, a wrapper around `debug`, to ensure proper namespace assignment.

To add a logger to code, require and invoke it:
To add a logger to code, import and invoke it with a channel:
```javascript
const logger = require('./cli/logger')();
import getLogger from './cli/logger';

const logger = getLogger();
logger.log('a message');
```

Optionally, pass the name of a feature or category when invoking the logger. This is useful for filtering log output.
```javascript
const okapiLogger = require('./cli/logger')('okapi');
import getLogger from './cli/logger';

const okapiLogger = getLogger('okapi');
okapiLogger.log('a message about Okapi');
```

Expand Down
6 changes: 1 addition & 5 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,2 @@
const { babelOptions } = require('@folio/stripes-webpack');

module.exports = {
babelOptions,
};
export { babelOptions } from '@folio/stripes-webpack';

12 changes: 8 additions & 4 deletions lib/cli/config.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
const findUp = require('find-up');
const fs = require('fs');
const logger = require('./logger')();
import findUp from 'find-up';
import fs from 'fs';

import getLogger from './logger.js';

const logger = getLogger();

// Maintain backwards compatibility for plugins referencing previous commands
const pluginMap = {
Expand Down Expand Up @@ -63,7 +66,8 @@ const commandDirOptions = cliConfig.plugins ? { visit: applyCommandPlugin } : {}
const yargsConfig = Object.assign({}, cliConfig);
delete yargsConfig.plugins;

module.exports = {

export default {
yargsConfig,
commandDirOptions,
configPath,
Expand Down
11 changes: 3 additions & 8 deletions lib/cli/context-middleware.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,14 @@
const context = require('./context');
import context from './context.js';

// Exposed separately for commands to change context if necessary
function applyContext(argv) {
export function applyContext(argv) {
const cliContext = Object.assign({}, context.getContext(argv.workingDir || ''));
return Object.assign(argv, { context: cliContext });
}

// Context middleware applies CLI context to argv
function contextMiddleware() {
export function contextMiddleware() {
return (argv) => {
return Promise.resolve(applyContext(argv));
};
}

module.exports = {
applyContext,
contextMiddleware,
};
32 changes: 19 additions & 13 deletions lib/cli/context.js
Original file line number Diff line number Diff line change
@@ -1,24 +1,30 @@
const path = require('path');
const fs = require('fs');
const importLazy = require('import-lazy')(require);
const isInstalledGlobally = require('is-installed-globally');
const isPathInside = require('is-path-inside');
const logger = require('./logger')();
import path from 'path';
import fs from 'fs';

import isInstalledGlobally from 'is-installed-globally';
import isPathInside from 'is-path-inside';
import { XMLParser } from 'fast-xml-parser';

import getLogger from './logger.js';

// TODO: Yarn 1.5.1 changed global install directory on Windows, 'global-dirs' does not yet reflect this
// https://github.com/yarnpkg/yarn/pull/5336
const globalDirs = require('./global-dirs');
const { stripesModules, toFolioName } = require('../environment/inventory');
import globalDirs from './global-dirs.js';

import { stripesModules, toFolioName } from '../environment/inventory.js';

const { XMLParser } = importLazy('fast-xml-parser');
const logger = getLogger();

const cliRoot = path.join(__dirname, '..', '..');
const cliRoot = path.join(import.meta.dirname, '..', '..');

const context = {
require, // add require to make it possible to mock it in the tests
// @@TODO
require: () => { },
// require, // add require to make it possible to mock it in the tests
};

function isGlobalYarn() {
return isPathInside(__dirname, globalDirs.yarn.packages);
return isPathInside(import.meta.dirname, globalDirs.yarn.packages);
}

function isUiModule(actsAs) {
Expand Down Expand Up @@ -137,4 +143,4 @@ context.getContext = (...args) => {
return resultContext;
};

module.exports = context;
export default context;
4 changes: 2 additions & 2 deletions lib/cli/generate-module-descriptor.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Logic borrowed from stripes-core's package2md.js excluding file load and console output
// $ node ../stripes-core/util/package2md.js package.json > MD.json
module.exports = function generateModuleDescriptor(packageJson, isStrict) {
export default function generateModuleDescriptor(packageJson, isStrict) {
const stripes = packageJson.stripes || {};
const moduleDescriptor = {
id: `${packageJson.name.replace(/^@/, '').replace('/', '_')}-${packageJson.version}`,
Expand All @@ -14,4 +14,4 @@ module.exports = function generateModuleDescriptor(packageJson, isStrict) {
moduleDescriptor.optional = Object.keys(optional).map(key => ({ id: key, version: optional[key] }));
}
return moduleDescriptor;
};
}
14 changes: 8 additions & 6 deletions lib/cli/global-dirs.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
const globalDirs = require('global-dirs');
const semver = require('semver');
const childProcess = require('child_process');
const path = require('path');
const logger = require('./logger')('global-dirs');
import globalDirs from 'global-dirs';
import semver from 'semver';
import childProcess from 'child_process';
import path from 'path';
import getLogger from './logger.js';

const logger = getLogger('global-dirs');

function isYarnVersion(version) {
try {
Expand All @@ -24,4 +26,4 @@ if (process.platform === 'win32' && isYarnVersion('>=1.5.1')) {
logger.log('Updated globalDirs.yarn:', globalDirs.yarn);
}

module.exports = globalDirs;
export default globalDirs;
6 changes: 3 additions & 3 deletions lib/cli/logger.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
const debug = require('debug');
import debug from 'debug';

// Wrapper for debug to ensure consistent use of namespace
module.exports = function getLogger(name) {
export default function getLogger(name) {
const namespace = name ? `stripes-cli:${name}` : 'stripes-cli';
const logger = debug(namespace);

return {
log: (...args) => logger(...args),
};
};
}
14 changes: 6 additions & 8 deletions lib/cli/prompt-middleware.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
const importLazy = require('import-lazy')(require);

const inquirer = importLazy('inquirer');
import inquirer from 'inquirer';

// Convert Yargs CLI options to Inquire.js questions
// This allows options/questions to be defined in a consistent format
function yargsToInquirer(yargsOptions) {
export function yargsToInquirer(yargsOptions) {
return Object.keys(yargsOptions).map((key) => {
const option = yargsOptions[key];
return Object.assign({}, {
Expand All @@ -21,7 +19,7 @@ function yargsToInquirer(yargsOptions) {
}

// Check for missing Yargs input and ask if necessary
function askIfUndefined(argv, yargsOptions) {
export function askIfUndefined(argv, yargsOptions) {
const askFor = {};
Object.keys(yargsOptions).forEach((key) => {
// Also check for yargs alias
Expand All @@ -38,12 +36,12 @@ function askIfUndefined(argv, yargsOptions) {
}

// Returns middleware to prompt for missing input prior to running command
function promptMiddleware(yargsOptions) {
export function promptMiddleware(yargsOptions) {
return (argv) => askIfUndefined(argv, yargsOptions);
}

module.exports = {
yargsToInquirer,
export default {
askIfUndefined,
promptMiddleware,
yargsToInquirer,
};
24 changes: 13 additions & 11 deletions lib/cli/stdin-middleware.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
const stdinWrapper = require('./stdin');
const logger = require('./logger')('stdinMiddleware');
import getStdinWrapper from './stdin.js';
import getLogger from './logger.js';

function stdinStringMiddleware(name) {
const logger = getLogger('stdinMiddleware');

export function stdinStringMiddleware(name) {
return (argv) => {
return stdinWrapper.getStdin().then(stdin => {
return getStdinWrapper.getStdin().then(stdin => {
if (stdin) {
logger.log(`read string from stdin for key "${name}"`);
argv[name] = stdin;
Expand All @@ -13,9 +15,9 @@ function stdinStringMiddleware(name) {
};
}

function stdinJsonMiddleware(name) {
export function stdinJsonMiddleware(name) {
return (argv) => {
return stdinWrapper.getStdin().then(stdin => {
return getStdinWrapper.getStdin().then(stdin => {
if (stdin) {
logger.log(`parsing JSON from stdin for key "${name}"`);
argv[name] = JSON.parse(stdin);
Expand All @@ -25,9 +27,9 @@ function stdinJsonMiddleware(name) {
};
}

function stdinArrayMiddleware(name) {
export function stdinArrayMiddleware(name) {
return (argv) => {
return stdinWrapper.getStdin().then(stdin => {
return getStdinWrapper.getStdin().then(stdin => {
if (stdin) {
logger.log(`parsing array from stdin for key "${name}"`);
argv[name] = stdin.trim().split(/\s+/);
Expand All @@ -37,9 +39,9 @@ function stdinArrayMiddleware(name) {
};
}

function stdinArrayOrJsonMiddleware(name) {
export function stdinArrayOrJsonMiddleware(name) {
return (argv) => {
return stdinWrapper.getStdin().then(stdin => {
return getStdinWrapper.getStdin().then(stdin => {
if (stdin) {
// Simple check for starting character of '{' or '[' to determine how to handle the data
if (stdin.match(/^\s*[{[]/)) {
Expand All @@ -55,7 +57,7 @@ function stdinArrayOrJsonMiddleware(name) {
};
}

module.exports = {
export default {
stdinStringMiddleware,
stdinJsonMiddleware,
stdinArrayMiddleware,
Expand Down
11 changes: 5 additions & 6 deletions lib/cli/stdin.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
const getStdin = require('get-stdin');
import wrappedGetStdin from 'get-stdin';

function stdinWrapper() {
function getStdin() {
// Per Node docs, the preferred method of determining whether Node.js is being run within
// a TTY context is to check that the value of the process.stdout.isTTY property is true
// (https://nodejs.org/docs/latest-v8.x/api/tty.html)
if (process.stdout.isTTY) {
return getStdin();
return wrappedGetStdin();
} else {
return Promise.resolve();
}
}

// Wrapper to facilitate testing
module.exports = {
getStdin: stdinWrapper,
export default {
getStdin
};
4 changes: 2 additions & 2 deletions lib/cli/stripes-cli-error.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
module.exports = class StripesCliError extends Error {
export default class StripesCliError extends Error {
constructor(...args) {
super(...args);
this.name = this.constructor.name;
Error.captureStackTrace(this, StripesCliError);
}
};
}
16 changes: 7 additions & 9 deletions lib/cli/stripes-config-middleware.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
const path = require('path');
const { stdinJsonMiddleware } = require('./stdin-middleware');
const StripesCliError = require('./stripes-cli-error');
const logger = require('./logger')('stripesConfigMiddleware');
import path from 'path';
import { stdinJsonMiddleware } from './stdin-middleware.js';
import StripesCliError from './stripes-cli-error.js';
import getLogger from './logger.js';

const logger = getLogger('stripesConfigMiddleware');


function loadStripesConfig(stripesConfigFile) {
Expand All @@ -27,7 +29,7 @@ async function readStripesConfigStdin() {
// Given a "--configFile" has been provided, this middleware will load the stripes configuration from disk
// and make the stripes configuration object available to the command as "argv.stripesConfig"
// If no configFile has been provided, stdin is checked for JSON input
function stripesConfigMiddleware(fileOnly) {
export function stripesConfigMiddleware(fileOnly) {
return async function middleware(argv) {
logger.log('initializing...');
let stripesConfig;
Expand Down Expand Up @@ -57,7 +59,3 @@ function stripesConfigMiddleware(fileOnly) {
return Promise.resolve(argv);
};
}

module.exports = {
stripesConfigMiddleware,
};
21 changes: 13 additions & 8 deletions lib/cli/stripes-core.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
const path = require('path');
const resolvePkg = require('resolve-pkg');
const resolveFrom = require('resolve-from');
const importLazy = require('import-lazy');
const logger = require('./logger')();
const getStripesWebpackConfig = require('../test/webpack-config');
import path from 'path';
import resolvePkg from 'resolve-pkg';
import resolveFrom from 'resolve-from';
import importLazy from 'import-lazy';
import { createRequire } from 'module';

import getLogger from './logger.js';
import getStripesWebpackConfig from '../test/webpack-config.js';

const logger = getLogger();
const require = createRequire(import.meta.url);

// Wraps stripes-core modules and API:
// Includes centralized logic to locate stripes-core for build and runtime
module.exports = class StripesCore {
export default class StripesCore {
constructor(context, aliases) {
this.context = context;
this.coreAlias = aliases['@folio/stripes-webpack'];
Expand Down Expand Up @@ -76,4 +81,4 @@ module.exports = class StripesCore {
getStripesWebpackConfig(...args) {
return getStripesWebpackConfig(this, ...args);
}
};
}
Loading
Loading