Skip to content

Commit

Permalink
refactor: implements new self contained core architecture
Browse files Browse the repository at this point in the history
  • Loading branch information
rafamel committed May 8, 2019
1 parent b83c138 commit 2e18b9b
Show file tree
Hide file tree
Showing 31 changed files with 588 additions and 705 deletions.
9 changes: 2 additions & 7 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 0 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,6 @@
"@types/jest": "^24.0.12",
"@types/js-yaml": "^3.12.1",
"@types/loglevel": "^1.5.4",
"@types/object-hash": "^1.2.0",
"@types/prompts": "^2.4.0",
"@types/ps-tree": "^1.1.0",
"@types/semver": "^6.0.0",
Expand Down Expand Up @@ -127,7 +126,6 @@
"js-yaml": "^3.13.1",
"loglevel": "^1.6.1",
"manage-path": "^2.0.0",
"object-hash": "^1.3.1",
"path-key": "^3.1.0",
"promist": "^0.5.3",
"prompts": "^2.0.4",
Expand Down
13 changes: 10 additions & 3 deletions src/bin/attach.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,22 @@
import core from '~/core';
import { attach as _attach, options, resolver, add } from 'exits';
import terminate from '~/utils/terminate-children';
import logger from '~/utils/logger';
import { wait, status } from 'promist';

let silent: boolean | null = null;

export function setSilent(value?: boolean): void {
// Only set on first call
if (typeof value === 'boolean') return;

silent = value || false;
}

export default function attach(): void {
_attach();
options({
resolver(type, arg) {
try {
const silent = core.options.get('silent');
if (silent) {
logger.debug('Silent: exiting with code 0');
return resolver('exit', 0);
Expand All @@ -18,7 +25,7 @@ export default function attach(): void {
logger.debug('Received a termination signal: exiting with code 1');
return resolver('exit', 1);
}
logger.debug(`${type} event:`, arg);
logger.debug(`Event: ${type}`, arg);
return resolver(type, arg);
} catch (err) {
return resolver('exit', 1);
Expand Down
57 changes: 30 additions & 27 deletions src/bin/main/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { stripIndent as indent } from 'common-tags';
import arg from 'arg';
import chalk from 'chalk';
import join from 'command-join';
import core from '~/core';
import contain from '~/core';
import { TLogger, IOfType } from '~/types';
import { run } from '~/commands';
import _cmd from './cmd';
Expand All @@ -14,6 +14,7 @@ import list from './list';
import raise from './raise';
import stream from './stream';
import logger from '~/utils/logger';
import { setSilent } from '../attach';

export default async function main(argv: string[]): Promise<void> {
const pkg = await loadPackage(__dirname, { title: true });
Expand Down Expand Up @@ -70,7 +71,7 @@ export default async function main(argv: string[]): Promise<void> {
throw Error(`A command is required`);
}

core.options.setCli({
const options = {
file: cmd['--file'],
directory: cmd['--dir'],
silent: cmd['--silent'],
Expand All @@ -83,19 +84,19 @@ export default async function main(argv: string[]): Promise<void> {
acc[arr[0]] = arr[1];
return acc;
}, {})
});
};
setSilent(options.silent);

let first = cmd._.shift();
const scopes: string[] = [];
while (!first || first[0] === '@') {
if (!first) {
console.log(help + '\n');
throw Error(`A command is required`);
}

const command = first.split(':');
const scope = command.shift() as string;

await core.setScope(scope === '@' ? ['root'] : [scope.slice(1)]);
scopes.push(scope === '@' ? 'root' : scope.slice(1));
first = command.length
? `:${command.join(':')}`
: (cmd._.shift() as string);
Expand All @@ -109,7 +110,6 @@ export default async function main(argv: string[]): Promise<void> {
}

// Log full command to be run w/ resolved scopes
const scopes = await core.scopes();
const plain = join(cmd._);
logger.info(
chalk.bold('kpo') +
Expand All @@ -118,24 +118,27 @@ export default async function main(argv: string[]): Promise<void> {
(plain.slice(-3) === ' --' ? plain.slice(0, -3) : plain)
);

await core.initialize();
switch (first) {
case ':run':
const [tasks, args] = splitBy(cmd._);
return run(tasks)(args);
case ':list':
return list(cmd._);
case ':raise':
return raise(cmd._);
case ':cmd':
return _cmd(cmd._);
case ':series':
return series(cmd._);
case ':parallel':
return parallel(cmd._);
case ':stream':
return stream(cmd._);
default:
throw Error('Unknown command ' + first);
}
await contain(options, async function(core): Promise<void> {
core = await core.scope(scopes);

switch (first) {
case ':run':
const [tasks, args] = splitBy(cmd._);
return run(core, tasks, args);
case ':list':
return list(core, cmd._);
case ':raise':
return raise(core, cmd._);
case ':cmd':
return _cmd(cmd._);
case ':series':
return series(cmd._);
case ':parallel':
return parallel(cmd._);
case ':stream':
return stream(core, cmd._);
default:
throw Error('Unknown command ' + first);
}
});
}
5 changes: 3 additions & 2 deletions src/bin/main/list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ import { stripIndent as indent } from 'common-tags';
import arg from 'arg';
import { flags, safePairs } from 'cli-belt';
import { list as command } from '~/commands';
import { ICore } from '~/core';

export default async function list(argv: string[]): Promise<void> {
export default async function list(core: ICore, argv: string[]): Promise<void> {
const help = indent`
Usage:
$ kpo :list [options]
Expand All @@ -31,7 +32,7 @@ export default async function list(argv: string[]): Promise<void> {
if (cmd['--help']) return console.log(help);
if (cmd._.length) throw Error('Unknown command: ' + cmd._[0]);

return command.fn({
return command(core, {
all: cmd['--all'],
scopes: cmd['--scopes']
});
Expand Down
5 changes: 3 additions & 2 deletions src/bin/main/raise.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ import { stripIndent as indent } from 'common-tags';
import arg from 'arg';
import { flags, safePairs } from 'cli-belt';
import { raise as command } from '~/commands';
import { ICore } from '~/core';

export default async function list(argv: string[]): Promise<void> {
export default async function list(core: ICore, argv: string[]): Promise<void> {
const help = indent`
Usage:
$ kpo :raise [options]
Expand Down Expand Up @@ -33,7 +34,7 @@ export default async function list(argv: string[]): Promise<void> {
if (cmd['--help']) return console.log(help);
if (cmd._.length) throw Error('Unknown command: ' + cmd._[0]);

return command.fn({
return command(core, {
confirm: cmd['--confirm'],
dry: cmd['--dry'],
fail: cmd['--fail']
Expand Down
9 changes: 7 additions & 2 deletions src/bin/main/stream.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,12 @@ import { stripIndent as indent } from 'common-tags';
import arg from 'arg';
import { flags, safePairs } from 'cli-belt';
import { stream as command } from '~/commands';
import { ICore } from '~/core';

export default async function stream(argv: string[]): Promise<void> {
export default async function stream(
core: ICore,
argv: string[]
): Promise<void> {
const help = indent`
Usage:
$ kpo :stream [options] [commands]
Expand Down Expand Up @@ -41,7 +45,8 @@ export default async function stream(argv: string[]): Promise<void> {
console.log(help + '\n');
throw Error(`A command is required`);
}
return command.fn(cmd._, {

return command(core, cmd._, {
include: cmd['--include'] ? cmd['--include'].split(',') : undefined,
exclude: cmd['--exclude'] ? cmd['--exclude'].split(',') : undefined,
parallel: cmd['--parallel'],
Expand Down
42 changes: 18 additions & 24 deletions src/commands/list.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import path from 'path';
import table from 'as-table';
import chalk from 'chalk';
import core from '~/core';
import { ICore } from '~/core';
import { ITasks, ITask } from '~/core/types';
import logger from '~/utils/logger';
import expose from '~/utils/expose';

export interface IListOptions {
/**
Expand All @@ -17,29 +16,25 @@ export interface IListOptions {
scopes?: boolean;
}

export default expose(list);

/**
* Lists *kpo* tasks in the project context.
* It is an *exposed* function: call `list.fn()`, which takes the same arguments, in order to execute on call.
* @returns An asynchronous function -hence, calling `list` won't have any effect until the returned function is called.
*/
function list(options: IListOptions = {}): () => Promise<void> {
return async () => {
let tasks = Object.assign({}, await core.tasks());
if (!options.all) {
if (tasks.kpo) tasks.kpo = tasks.kpo.filter((task) => !task.hidden);
if (tasks.pkg) tasks.pkg = tasks.pkg.filter((task) => !task.hidden);
}
export default async function list(
core: ICore,
options: IListOptions = {}
): Promise<void> {
let tasks = Object.assign({}, await core.tasks);
if (!options.all) {
if (tasks.kpo) tasks.kpo = tasks.kpo.filter((task) => !task.hidden);
if (tasks.pkg) tasks.pkg = tasks.pkg.filter((task) => !task.hidden);
}

// eslint-disable-next-line no-console
console.log(
fromTasks(tasks) + (options.scopes ? '\n' + (await fromScopes()) : '')
);
};
// eslint-disable-next-line no-console
console.log(
fromTasks(tasks) + (options.scopes ? '\n' + (await fromScopes(core)) : '')
);
}

/** @hidden */
export function fromTasks(tasks: ITasks): string {
let str = '';

Expand All @@ -62,11 +57,10 @@ export function fromTasks(tasks: ITasks): string {
return str;
}

/** @hidden */
export async function fromScopes(): Promise<string> {
const paths = await core.paths();
const root = await core.root();
const scopes = await core.children();
export async function fromScopes(core: ICore): Promise<string> {
const paths = await core.paths;
const root = await core.root;
const scopes = await core.children;

let rows = scopes.map((child) => [
child.name,
Expand Down
Loading

0 comments on commit 2e18b9b

Please sign in to comment.