Repository: pawelgalazka/runjs
Branch: master
Commit: 6258ca6cbfa5
Files: 24
Total size: 31.1 KB
Directory structure:
gitextract_wxdegntt/
├── .babelrc
├── .gitignore
├── .huskyrc.json
├── .npmignore
├── .npmrc
├── .prettierrc.json
├── .travis.yml
├── CHANGELOG.md
├── LICENSE
├── README.md
├── bin/
│ └── task.js
├── jest.config.js
├── package.json
├── src/
│ ├── index.spec.ts
│ └── index.ts
├── test/
│ ├── __snapshots__/
│ │ └── e2e.spec.ts.snap
│ ├── e2e.spec.ts
│ └── sandbox/
│ ├── package.json
│ ├── scripts/
│ │ ├── color.js
│ │ ├── error.js
│ │ └── hello.js
│ └── tasksfile.js
├── tsconfig.json
└── tslint.json
================================================
FILE CONTENTS
================================================
================================================
FILE: .babelrc
================================================
{
"presets": ["@babel/preset-env", "@babel/preset-typescript"]
}
================================================
FILE: .gitignore
================================================
.idea
.vscode
.DS_Store
node_modules
npm-debug.log
/coverage
/lib
================================================
FILE: .huskyrc.json
================================================
{
"hooks": {
"pre-commit": "lint-staged"
}
}
================================================
FILE: .npmignore
================================================
*.spec.ts
/src
/test
/.huskyrc.json
/.travis.yml
/.prettierrc.json
/.vscode
/.babelrc
/test
/jest.config.js
/tslint.json
/tsconfig.json
================================================
FILE: .npmrc
================================================
save-exact=true
================================================
FILE: .prettierrc.json
================================================
{
"semi": false,
"singleQuote": true
}
================================================
FILE: .travis.yml
================================================
language: node_js
node_js:
- "8.15.0"
- "10.15.0"
================================================
FILE: CHANGELOG.md
================================================
## 5.1.0
*API:*
- `sh` function now accepts different set of options. Most importantly it does not accept
`stdio` option anymore. By default it will be always in `stdio=pipe` mode for `stdout`
and `stderr` process streams. It will also print out results to the terminal unless `silent=true`
option given.
- `sh` function accepts also `transform` option which allows to transform output of
shell process. Usefull if we want to add prefixes to the output.
- introducing `prefixTransform` function. It is dedicated for usage along with `sh`
function as value for `transform` option.
## 5.0.0
*API:*
- `help` function as second argument now accepts only `string`, for third argument
accepts detailed help information about `options` and `params`
- removing `option` and `options` helper, now `options` will be passed always as a first
argument to the task
- introducing `rawArgs` function, which returns raw, unparsed args which were provided
to the task
- renaming `run` function to `sh`
- introducing `cli` function which exposes tasks functions to the cli
*Mechanics:*
- `options` are always passed as a first argument to the task function
- calling tasks occurs through `npx task` not `npx run` script or by calling
`tasksfile.js` directly (`node tasksfile.js`). Tasks file now behaves like a
CLI script
- to be able to call tasks from `tasksfile.js` they must be exposed by `cli`
function. Exporting tasks functions won't do the job anymore.
- to be able to call a task through `npx task`, entry to `npm scripts` must be added:
`"task": "node ./tasksfile.js"`. `npx task` always try to execute `task` npm script,
it's just an alias.
- namespaces now can have `default` task
- removing autocomplete feature, as it required too much configuration and it
seems not used by the users
- full support for `TypeScript`. Types files are included within the project. Using
`TypeScript` for `tasksfile` is possible. It just require different entry in `npm scripts`:
`"task": "ts-node ./tasksfile.ts"`
*Other:*
- renaming project from `runjs` to `tasksfile`
## 4.4.0
- source code migrated from `Flow/Babel` to `TypeScript`
## 4.3.0
- adding experimental bash autocompletion feature
## 4.2.0
*Changes:*
- introducing `help` utility function
- improving task docs generation by annotations
*Dev env:*
- improving e2e tests
- using external module `microcli` as for cli args parsing and `--help` handling
## 4.1.0
- remove log option from `run` api command
- upgrade dependent packages
- introducing `options` helper, deprecating `option`
- better printing of methods list when calling `run`
*For development env:*
- add tests coverage check
- introducing `flow` types
## 4.0.0
**Changes:**
- removing `ask` and `generate` helpers from api, to keep runjs codebase more focused about its main purpose
- dropping support for `node` < 6.11.1
- support for other than `Babel` transpilers, like `TypeScript`
- log option to run function, when `false` it does not log the command
- documentation updates
- support for `async` / `await`
- `option` helper
**Migration from 3.x to 4.x procedure:**
- make sure you have node version >=6.11.1
- if you use Babel you need to add `"runjs": {requires: ["./node_modules/babel-register"]}` config to your package.json, otherwise Babel transpiler won't be picked up
- find alternatives for ask and generate, those are not supported by runjs anymore
## 3.4.1
- changing documentation format for calling `run` without arguments (task documentation)
- changing name of the prop for documentation from doc to help
- when typing `--help` option with task run it will provide documentation only for that task (`run sometask --help`)
## 3.3.0
- migrating to `yarn`
- removing task execution logging (decoration function) as it not working well with exporting pure functions
- passing task options through `this.options` inside a task function
## 3.2.1
- fixes within handling dashed arguments when calling tasks, dashed arguments can be "spaced" by "-" or "." now, for example: `--some-argument` or `--some.argument` (#49)
## 3.2.0
- documenting tasks args when calling `run` without arguments
- presenting list of available tasks from `runfile.js` in more readable way
- passing `stdio` directly to `spawn` / `execSync`
- changing run api where now it resolves/returns null by default and resolves/returns with value for option stdio: 'pipe'. This - allows to return colours to the terminal if provided by commands outcome.
## 3.1.1
- Bug fix: pass `process.env` by default to `spawn` and `execSync`
## 3.1.0
- fixes #43 `stderr` maxBuffer exceeded error (use `spawn` for `async` calls not `exec`)
- `runfile.js` example update in README
- drops support for `node` < 4.8.0
## 3.0.0
- task name spacing/nesting, better for scaling tasks into many files
- task descriptions
- `ask` function
- handling dash arguments in tasks (for example `--test`, `-t`)
- logging tasks arguments to console when executing tasks
- fixing exit codes when task not found
- `run` function returns an output of a command now
- improving documentation
- deep code refactor, more unit tests
## 2.6.1
- bugfix: streaming `stderr` also for `async` process
## 2.6.0
- streaming output of an `async` command by default (`run` api function)
## 2.5.1
- presenting straightforward message when no `runfile.js` found
## 2.5.0
- bringing backwards compatibility with `node` >= 4.0.0 (previously `node` >= 6.0.0 required)
- `run` command in `async` mode now returns a `Promise`
## 2.4.3
- handling config from `package.json` to define a custom path to `babel-register`
- executing async commands through `child_process.span` (better `stdio` handling)
## 2.4.0
- removing watch method from api
- RunJS will fallback to pure node now if user `babel-register` not found (falling back to it's own `babel-register` before)
adding information to README: Why RunJS ? and other README update
## 2.3.0
- dropping Babel 5 support
- handling new `exports.default` after babel update
## 2.2.0
- more explicit exceptions
- handling existing `babel-register` or `babel/register` require hooks from the user package
## 2.1.0
- new functions available as part of runjs api: `watch` and `generate`
- broader README with extensive `runfile.js` example
## 2.0.0
- dropping `es5` and `coffeescript` support in favor of `es6` (handled by babel)
- dropping support for `node` < 4.0
================================================
FILE: LICENSE
================================================
The MIT License (MIT)
Copyright (c) 2015 Paweł Gałązka
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: README.md
================================================
# tasksfile  [](https://travis-ci.org/pawelgalazka/tasksfile) [](https://badge.fury.io/js/tasksfile)
Minimalistic building tool
> From version >= 5 RunJS was renamed to Tasksfile.
> Link to RunJS version: https://github.com/pawelgalazka/runjs/tree/runjs
- [Get started](#get-started)
- [Why tasksfile ?](#why-tasksfile-)
- [Features](#features)
- [Executing shell commands](#executing-shell-commands)
- [Handling arguments](#handling-arguments)
- [Documenting tasks](#documenting-tasks)
- [Namespacing](#namespacing)
- [Sharing tasks](#sharing-tasks)
- [TypeScript support](#typescript-support)
- [API](#api)
- [sh](#shcmd-options)
- [prefixTransform](#prefixTransformprefix)
- [help](#helpfunc-description-annotation)
- [rawArgs](#rawArgs)
## Get started
Install tasksfile in your project
npm install tasksfile --save-dev
Create `tasksfile.js` in your root project directory:
```js
const { sh, cli } = require('tasksfile')
function hello(options, name = 'Mysterious') {
console.log(`Hello ${name}!`)
}
function makedir() {
sh('mkdir somedir')
}
cli({
hello,
makedir
})
```
Create `task` entry in your `scripts` section in `package.json`:
```json
{
"scripts": {
"task": "node ./tasksfile.js"
}
}
```
Call in your terminal through npm scripts:
```bash
$ npm run task -- hello Tommy
$ npm run task -- makedir
$ yarn task hello Tommy
$ yarn task makedir
```
or through shorter `npx task` alias:
```bash
$ npx task hello Tommy
Hello Tommy!
$ npx task makedir
mkdir somedir
```
## Why tasksfile ?
We have Grunt, Gulp, npm scripts, Makefile. Why another building tool ?
Gulp or Grunt files seem overly complex for what they do and the plugin
ecosystem adds a layer of complexity towards the simple command
line tools underneath. The documentation is not always up to date
and the plugin does not always use the latest version of the tool.
After a while customizing the process even with simple things,
reconfiguring it becomes time consuming.
Npm scripts are simple but they get out of hand pretty quickly if
we need more complex process which make them quite hard to read
and manage.
Makefiles are simple, better for more complex processes
but they depend on bash scripting. Within `tasksfile` you can use
command line calls as well as JavaScript code and npm
libraries which makes that approach much more flexible.
[More](https://hackernoon.com/simple-build-tools-npm-scripts-vs-makefile-vs-runjs-31e578278162)
## Features
### Executing shell commands
Tasksfile gives an easy way to execute shell commands in your tasks by `sh` function
in synchronous and asynchronous way:
```js
const { sh, cli } = require('tasksfile')
function command () {
sh('jest')
sh(`webpack-dev-server --config webpack.config.js`, {
async: true
})
}
cli({
command
})
```
```bash
$ npx task command
```
Because `./node_modules/.bin` is included in `PATH` when calling shell commands
by `sh` function, you can call "bins" from your local project in the same way as
in npm scripts.
### Handling arguments
Provided arguments in the command line are passed to the function:
```javascript
function sayHello (options, who) {
console.log(`Hello ${who}!`)
}
cli({
sayHello
})
```
```bash
$ npx task sayHello world
Hello world!
```
You can also provide dash arguments like `-a` or `--test`. Order of them doesn't
matter after task name. They will be always available by `options` helper
from inside a function.
```javascript
function sayHello (options, who) {
console.log(`Hello ${who}!`)
console.log('Given options:', options)
}
cli({
sayHello
})
```
```bash
$ npx task sayHello -a --test=something world
Hello world!
Given options: { a: true, test: 'something' }
```
### Documenting tasks
To display all available tasks for your `tasksfile.js` type `task` in your command line
without any arguments:
$ npx task --help
Commands:
echo - echo task description
buildjs - Compile JS files
Use `help` utility function for your task to get additional description:
```javascript
const { cli, help } = require('tasksfile')
function buildjs () {
}
help(buildjs, 'Compile JS files')
cli({
buildjs
})
```
$ npx task buildjs --help
Usage: buildjs
Compile JS files
You can provide detailed annotation to give even more info about the task:
```javascript
const dedent = require('dedent')
const { sh, help } = require('tasksfile')
function test (options, file) {
}
help(test, 'Run unit tests', {
params: ['file'],
options: {
watch: 'run tests in a watch mode'
},
examples: dedent`
task test dummyComponent.js
task test dummyComponent.js --watch
`
})
cli({
test
})
```
$ npx task test --help
Usage: test [options] [file]
Run unit tests
Options:
--watch run tests in a watch mode
Examples:
task test dummyComponent.js
task test dummyComponent.js --watch
### Namespacing
To better organise tasks, it is possible to call them from namespaces:
```js
const test = {
unit () {
console.log('Doing unit testing!')
}
}
cli({
test
})
```
```bash
$ npx task test:unit
Doing unit testing!
```
This is especially useful if `tasksfile.js` gets too large. We can move some tasks
to external modules and import them back to a namespace:
`./tasks/test.js`:
```javascript
function unit () {
console.log('Doing unit testing!')
}
function integration () {
console.log('Doing unit testing!')
}
function default() {
unit()
integration()
}
module.exports = {
unit,
integration,
default
}
```
`tasksfile.js`
```js
const test = require('./tasks/test')
cli({
test
})
```
```bash
$ npx task test:unit
Doing unit testing!
$ npx task test
Doing unit testing!
Doing integration testing!
```
If we don't want to put imported tasks into a namespace, we can always use spread
operator:
```js
cli({
...test
})
```
```bash
$ npx task unit
Doing unit testing!
```
With ES6 modules import/export syntax this becomes even simpler:
```js
// export with no namespace
export * from './tasks/test' // no namespace
// export with namespace
import * as test from './tasks/test'
export { test } // add namespace
```
```bash
$ npx task unit
$ npx task test:unit
```
### Sharing tasks
Because `tasksfile.js` is just a node.js module and `tasksfile` just calls exported
functions from that module based on cli arguments, nothing stops you to move
some repetitive tasks across your projects to external npm package and
just reuse it.
`shared-tasksfile` module:
```js
function shared1 () {
console.log('This task is shared!')
}
function shared2 () {
console.log('This task is shared!')
}
module.exports = {
shared1,
shared2
}
```
Local `tasksfile.js`
```js
const shared = require('shared-tasksfile')
function local () {
console.log('This task is local!')
}
cli({
...shared,
local
})
```
```bash
$ npx task shared1
$ npx task shared2
$ npx task local
```
### TypeScript support
It's very easy to run your tasks in `TypeScript` if you have `TypeScript` already
in your project. Just:
- change your `tasksfile.js` to `tasksfile.ts` and adjust the code
- install `ts-node`: `npm install --save-dev ts-node`
- change command in your `package.json`:
```json
{
"scripts": {
"task": "ts-node ./tasksfile.ts"
}
}
```
`Tasksfile` project already has `TypeScript` declaration files in source files.
## API
For inside `tasksfile.js` usage.
#### sh(cmd, options)
Run given command as a child process and log the call in the output.
`./node_modules/.bin/` is included into `PATH` so you can call installed scripts directly.
Function will return output of executed command.
```js
const { sh } = require('tasksfile')
```
*Options:*
```ts
interface IShellOptions {
// current working directory
cwd?: string
// environment key-value pairs
env?: NodeJS.ProcessEnv
// timeout after which execution will be cancelled
timeout?: number
// default: false, if true it runs command asynchronously and returns a Promise
async?: boolean
// if true, it will send output directly to parent process (stdio="inherit"), it won't return the output though
// usefull if default piping strips too much colours when printing to the terminal
// if enabled, transform option won't work
nopipe?: boolean
// if true, it won't print anything to the terminal but it will still return the output as a string
silent?: boolean
// function which allows to transform the output, line by line
// usefull for adding prefixes to async commands output
transform?: (output: string) => string
}
```
#### prefixTransform(prefix)
Transform function which can be used as `transform` option of `sh` function.
It allows to add prefixes to shell output.
*Example:*
```js
const { cli, sh, prefixTransform } = require('tasksfile')
function test() {
sh('echo "test"', {
transform: prefixTransform('[prefix]')
})
}
cli({
test
})
```
```sh
$ npx task test
echo "test"
[prefix] test
```
#### help(func, description, annotation)
Define help annotation for task function, so it will be printed out when calling task with `--help`
option and when calling `run` without any arguments.
```js
const { help } = require('tasksfile')
```
```javascript
help(build, 'Generate JS bundle')
help(test, 'Run unit tests', {
params: ['file'],
options: {
watch: 'run tests in a watch mode'
},
examples: `
task test dummyComponent.js
task test dummyComponent.js --watch
`
})
```
$ npx task build --help
$ npx task test --help
#### rawArgs()
Returns arguments / options passed to task in a raw, unparsed format.
```javascript
const { cli, rawArgs } = require('tasksfile')
function hello(options) {
console.log('RAW ARGS', rawArgs())
}
cli({
hello
})
```
```sh
$ npx task hello 1 2 3 --test
RAW ARGS ['1', '2', '3', '--test']
```
================================================
FILE: bin/task.js
================================================
#!/usr/bin/env node
const { execSync } = require('child_process')
const path = require('path')
const packageJson = require(path.resolve('./package.json'))
const taskScript = packageJson.scripts.task
try {
execSync(`${taskScript} ${process.argv.slice(2).join(' ')}`, {shell: true, stdio: 'inherit'})
} catch (error) {
process.exit(1)
}
================================================
FILE: jest.config.js
================================================
// For a detailed explanation regarding each configuration property, visit:
// https://jestjs.io/docs/en/configuration.html
module.exports = {
// A list of paths to directories that Jest should use to search for files in.
roots: ["<rootDir>/src/", "<rootDir>/test/"],
// The test environment that will be used for testing
testEnvironment: "node",
// A list of reporter names that Jest uses when writing coverage reports
coverageReporters: [
"text",
"text-summary"
],
// An object that configures minimum threshold enforcement for coverage results
coverageThreshold: {
"global": {
"lines": 30
}
}
};
================================================
FILE: package.json
================================================
{
"name": "tasksfile",
"version": "5.1.1",
"description": "Minimalistic task runner for node.js",
"keywords": [
"build",
"system",
"make",
"tool"
],
"main": "lib/index.js",
"types": "lib/index.d.ts",
"bin": {
"task": "bin/task.js"
},
"scripts": {
"lint": "tslint -c tslint.json 'src/*.ts' 'test/**/*.ts'",
"build": "tsc",
"test": "yarn lint && yarn build && yarn clean:sandbox && jest --coverage",
"test:unit": "jest ./src/",
"test:e2e": "jest ./test/",
"clean": "rm -rf node_modules && yarn clean:build && yarn clean:sandbox",
"clean:build": "rm -rf ./lib",
"clean:sandbox": "rm -rf ./test/e2e/sandbox/node_modules && mkdir -p ./test/sandbox/node_modules/.bin",
"sandbox:task": "cd ./test/sandbox && ../../bin/task.js"
},
"lint-staged": {
"src/*.{ts,tsx}": [
"tslint --fix",
"git add"
]
},
"engines": {
"node": ">=6.11.1"
},
"repository": {
"type": "git",
"url": "git+https://github.com/pawelgalazka/tasksfile.git"
},
"author": "Pawel Galazka",
"license": "MIT",
"bugs": {
"url": "https://github.com/pawelgalazka/tasksfile/issues"
},
"homepage": "https://github.com/pawelgalazka/tasksfile#readme",
"dependencies": {
"@pawelgalazka/cli": "2.0.3",
"@pawelgalazka/shell": "2.0.0",
"chalk": "2.3.0"
},
"devDependencies": {
"@babel/core": "7.2.2",
"@babel/preset-env": "7.3.1",
"@babel/preset-typescript": "7.1.0",
"@types/jest": "24.0.0",
"@types/lodash.padend": "4.6.4",
"@types/node": "10.12.18",
"husky": "1.3.1",
"jest": "24.1.0",
"lint-staged": "8.1.0",
"prettier": "1.15.3",
"tslint": "5.12.1",
"tslint-config-prettier": "1.17.0",
"tslint-plugin-prettier": "2.0.1",
"typescript": "3.2.2"
}
}
================================================
FILE: src/index.spec.ts
================================================
import { shell } from '@pawelgalazka/shell'
import chalk from 'chalk'
import { sh } from './index'
const shellMock = shell as jest.Mock
jest.mock('@pawelgalazka/shell')
process.env = { DEFAULT_ENV: 'default env' }
describe('sh()', () => {
let logger: any
beforeEach(() => {
jest.resetAllMocks()
logger = {
error: jest.fn(),
log: jest.fn(),
title: jest.fn(),
warning: jest.fn()
}
})
it('calls original @pawelgalazka/shell function with the same command', () => {
sh('test command', undefined, logger)
expect(shellMock).toHaveBeenCalledTimes(1)
expect(shellMock).toHaveBeenCalledWith('test command', expect.anything())
})
it('logs executed command', () => {
sh('test command', undefined, logger)
expect(logger.log).toHaveBeenCalledTimes(1)
expect(logger.log).toHaveBeenCalledWith(chalk.bold('test command'))
})
it('calls original @pawelgalazka/shell with default options values', () => {
sh('test command', undefined, logger)
expect(shellMock).toHaveBeenCalledTimes(1)
expect(shellMock).toHaveBeenCalledWith(expect.anything(), {
env: {
DEFAULT_ENV: 'default env',
PATH: expect.anything()
}
})
})
it('calls original @pawelgalazka/shell with given options values', () => {
sh(
'test command',
{
async: true,
cwd: 'cwd-dir',
env: { CUSTOM_ENV: 'custom env' },
stdio: 'pipe',
timeout: 1000
},
logger
)
expect(shellMock).toHaveBeenCalledTimes(1)
expect(shellMock).toHaveBeenCalledWith(expect.anything(), {
async: true,
cwd: 'cwd-dir',
env: {
CUSTOM_ENV: 'custom env',
PATH: expect.anything()
},
stdio: 'pipe',
timeout: 1000
})
})
it('adds ./node_modules/.bin to $PATH', () => {
sh('test command', undefined, logger)
expect(shellMock).toHaveBeenCalledWith(
expect.anything(),
expect.objectContaining({
env: expect.objectContaining({
PATH: expect.stringContaining('node_modules/.bin:')
})
})
)
})
})
================================================
FILE: src/index.ts
================================================
import {
cli as cliEngine,
CLIError,
CommandsModule,
Middleware,
useMiddlewares
} from '@pawelgalazka/cli'
import { Logger } from '@pawelgalazka/cli/lib/utils/logger'
import {
IAsyncShellOptions,
IShellOptions,
ISyncShellOptions,
shell,
ShellError
} from '@pawelgalazka/shell'
import chalk from 'chalk'
import path from 'path'
export { help, rawArgs } from '@pawelgalazka/cli'
export { prefixTransform } from '@pawelgalazka/shell'
const commandNotFoundHandler: Middleware = next => args => {
const { command } = args
if (!command) {
throw new CLIError(
'Command not found. Type "npx task --help" for more information.'
)
}
next(args)
}
const shellErrorHandler: (
logger: Logger
) => Middleware = logger => next => args => {
const { reject } = args
const nextReject = (error: Error) => {
if (error instanceof ShellError) {
logger.error(error.message)
process.exit(1)
} else {
reject(error)
}
}
try {
next({
...args,
reject: nextReject
})
} catch (error) {
nextReject(error)
}
}
export function sh(
command: string,
options: IAsyncShellOptions,
logger?: Logger
): Promise<string | null>
export function sh(
command: string,
options?: ISyncShellOptions,
logger?: Logger
): string | null
export function sh(
command: string,
options: IShellOptions = {},
logger: Logger = new Logger()
) {
const binPath = path.resolve('./node_modules/.bin')
// Include in PATH node_modules bin path
const nextPath = [
binPath,
(options.env && options.env.PATH) || process.env.PATH
].join(path.delimiter)
const nextOptions = {
...options,
env: {
...(options.env || process.env),
PATH: nextPath
}
}
logger.log(chalk.bold(command))
return shell(command, nextOptions)
}
export function cli(definition: CommandsModule) {
return cliEngine(
definition,
useMiddlewares([commandNotFoundHandler, shellErrorHandler(new Logger())])
)
}
================================================
FILE: test/__snapshots__/e2e.spec.ts.snap
================================================
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`tasksfile displays commands list if only --help option provided and no task name 1`] = `
"
Commands:
asyncAwait
color
echo - Simple echo task
error
errorAsyncAwait
nested
nested:echo [p1 p2] - Description of nested task
npmBin
shell
"
`;
================================================
FILE: test/e2e.spec.ts
================================================
/* eslint-env jest */
import { execSync as orgExecSync } from 'child_process'
describe('tasksfile', () => {
const scriptPath = '../../bin/task.js'
function execSync(cmd: string) {
return orgExecSync(cmd, {
cwd: './test/sandbox',
env: {
...process.env,
FORCE_COLOR: '0'
},
stdio: 'pipe'
}).toString()
}
it('executes simple task', () => {
expect(execSync(`${scriptPath} echo 1 2 3 --foo --bar`)).toEqual(
"echo [ { foo: true, bar: true }, '1', '2', '3' ]\n"
)
})
it('executes shell commands in a task', () => {
const output = execSync(`${scriptPath} shell`)
expect(output).toContain(
'echo "sync terminal"\nsync terminal\necho "sync silent"\noutput sync silent'
)
expect(output).toContain('\nasync terminal\n')
expect(output).toContain('\noutput async silent\n')
})
it('executes task from a namespace', () => {
expect(execSync(`${scriptPath} nested:echo 1 2 3 --foo --bar`)).toEqual(
"nested echo [ { foo: true, bar: true }, '1', '2', '3' ]\n"
)
})
it('executes default task from a namespace', () => {
expect(execSync(`${scriptPath} nested 1 2 3 --foo --bar`)).toEqual(
"nested default [ { foo: true, bar: true }, '1', '2', '3' ]\n"
)
})
it('includes ./node_modules/.bin to PATH when executing bin scripts', () => {
execSync('cp -p ./scripts/hello.js ./node_modules/.bin/hello')
expect(execSync(`${scriptPath} npmBin`)).toEqual('hello\nHello!\n')
})
it('executes async/await task', () => {
expect(execSync(`${scriptPath} asyncAwait`)).toContain(
'echo "async and await"\noutput async and await\n\nafter await\n'
)
})
it('displays help for a task', () => {
expect(execSync(`${scriptPath} echo --help`)).toEqual(
'Usage: echo \n\nSimple echo task\n\n'
)
})
it('displays detailed help', () => {
expect(execSync(`${scriptPath} nested:echo --help`)).toEqual(
'Usage: nested:echo [options] [p1 p2]\n\nDescription of nested task\n\n' +
'Options:\n\n --foo foo option description\n' +
' --bar bar option description\n'
)
})
it('displays error from executed task', () => {
expect(() => execSync(`${scriptPath} error`)).toThrow(
`Command failed: ${scriptPath} error`
)
})
it('displays error from executed async task', () => {
expect(() => execSync(`${scriptPath} errorAsyncAwait`)).toThrow(
`Command failed: ${scriptPath} errorAsyncAwait`
)
})
it('displays commands list if only --help option provided and no task name', () => {
expect(execSync(`${scriptPath} --help`)).toMatchSnapshot()
})
})
================================================
FILE: test/sandbox/package.json
================================================
{
"name": "sandbox",
"private": true,
"version": "1.0.0",
"scripts": {
"task": "node ./tasksfile.js"
}
}
================================================
FILE: test/sandbox/scripts/color.js
================================================
const chalk = require('chalk')
console.log(chalk.yellow('This should be in yellow color'))
================================================
FILE: test/sandbox/scripts/error.js
================================================
throw new Error('error message')
================================================
FILE: test/sandbox/scripts/hello.js
================================================
#!/usr/bin/env node
console.log('Hello!')
================================================
FILE: test/sandbox/tasksfile.js
================================================
const { sh, help, cli } = require('../../lib')
help(echo, 'Simple echo task')
function echo(...args) {
console.log('echo', args)
}
const nested = {
echo(...args) {
console.log('nested echo', args)
},
default (...args) {
console.log('nested default', args)
}
}
help(nested.echo, 'Description of nested task', {
options: {
foo: 'foo option description',
bar: 'bar option description'
},
params: ['p1', 'p2']
})
function shell() {
sh('echo "sync terminal"')
console.log('output', sh('echo "sync silent"', {silent: true}))
sh('echo "async terminal"', { async: true })
sh('echo "async silent"', { async: true, silent: true}).then(output =>
console.log('output', output)
)
}
function npmBin() {
sh('hello')
}
async function asyncAwait() {
const output = await sh('echo "async and await"', {
async: true,
silent: true
})
console.log('output', output)
console.log('after await')
}
function error() {
sh('node ./scripts/error.js', { async: true })
sh('node ./scripts/error.js')
}
async function errorAsyncAwait() {
await Promise.reject(new Error('async await error'))
}
function color() {
sh('node ./scripts/color.js')
sh('node ./scripts/color.js', { async: true })
}
cli({
echo,
shell,
nested,
npmBin,
asyncAwait,
errorAsyncAwait,
error,
color
})
================================================
FILE: tsconfig.json
================================================
{
"compilerOptions": {
/* Basic Options */
"target": "es2015", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */
"module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
"lib": ["es2017"], /* Specify library files to be included in the compilation. */
"declaration": true, /* Generates corresponding '.d.ts' file. */
"sourceMap": true, /* Generates corresponding '.map' file. */
"outDir": "./lib", /* Redirect output structure to the directory. */
/* Strict Type-Checking Options */
"strict": true, /* Enable all strict type-checking options. */
/* Additional Checks */
"noUnusedLocals": true, /* Report errors on unused locals. */
"noUnusedParameters": true, /* Report errors on unused parameters. */
"noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
"noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
/* Module Resolution Options */
"moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
"baseUrl": "./", /* Base directory to resolve non-absolute module names. */
"esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
},
"include": [
"src/**/*"
],
"exclude": [
"**/*.spec.ts"
]
}
================================================
FILE: tslint.json
================================================
{
"extends": [
"tslint:latest", "tslint-config-prettier"
],
"rules": {
"prettier": true,
"max-classes-per-file": false,
"no-console": false,
"no-empty": false,
"no-shadowed-variable": false,
"no-submodule-imports": false
},
"rulesDirectory": ["tslint-plugin-prettier"]
}
gitextract_wxdegntt/ ├── .babelrc ├── .gitignore ├── .huskyrc.json ├── .npmignore ├── .npmrc ├── .prettierrc.json ├── .travis.yml ├── CHANGELOG.md ├── LICENSE ├── README.md ├── bin/ │ └── task.js ├── jest.config.js ├── package.json ├── src/ │ ├── index.spec.ts │ └── index.ts ├── test/ │ ├── __snapshots__/ │ │ └── e2e.spec.ts.snap │ ├── e2e.spec.ts │ └── sandbox/ │ ├── package.json │ ├── scripts/ │ │ ├── color.js │ │ ├── error.js │ │ └── hello.js │ └── tasksfile.js ├── tsconfig.json └── tslint.json
SYMBOL INDEX (12 symbols across 3 files)
FILE: src/index.ts
function sh (line 67) | function sh(
function cli (line 92) | function cli(definition: CommandsModule) {
FILE: test/e2e.spec.ts
function execSync (line 6) | function execSync(cmd: string) {
FILE: test/sandbox/tasksfile.js
function echo (line 5) | function echo(...args) {
method echo (line 10) | echo(...args) {
method default (line 14) | default (...args) {
function shell (line 27) | function shell() {
function npmBin (line 36) | function npmBin() {
function asyncAwait (line 40) | async function asyncAwait() {
function error (line 49) | function error() {
function errorAsyncAwait (line 54) | async function errorAsyncAwait() {
function color (line 58) | function color() {
Condensed preview — 24 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (35K chars).
[
{
"path": ".babelrc",
"chars": 66,
"preview": "{\n \"presets\": [\"@babel/preset-env\", \"@babel/preset-typescript\"]\n}"
},
{
"path": ".gitignore",
"chars": 66,
"preview": ".idea\n.vscode\n.DS_Store\nnode_modules\nnpm-debug.log\n/coverage\n/lib\n"
},
{
"path": ".huskyrc.json",
"chars": 52,
"preview": "{\n \"hooks\": {\n \"pre-commit\": \"lint-staged\"\n }\n}"
},
{
"path": ".npmignore",
"chars": 136,
"preview": "*.spec.ts\n/src\n/test\n/.huskyrc.json\n/.travis.yml\n/.prettierrc.json\n/.vscode\n/.babelrc\n/test\n/jest.config.js\n/tslint.json"
},
{
"path": ".npmrc",
"chars": 15,
"preview": "save-exact=true"
},
{
"path": ".prettierrc.json",
"chars": 42,
"preview": "{\n \"semi\": false,\n \"singleQuote\": true\n}"
},
{
"path": ".travis.yml",
"chars": 54,
"preview": "language: node_js\nnode_js:\n - \"8.15.0\"\n - \"10.15.0\"\n"
},
{
"path": "CHANGELOG.md",
"chars": 6405,
"preview": "## 5.1.0\n\n*API:*\n- `sh` function now accepts different set of options. Most importantly it does not accept\n`stdio` optio"
},
{
"path": "LICENSE",
"chars": 1081,
"preview": "The MIT License (MIT)\n\nCopyright (c) 2015 Paweł Gałązka\n\nPermission is hereby granted, free of charge, to any person obt"
},
{
"path": "README.md",
"chars": 10177,
"preview": "# tasksfile  [\nconst path = require('path')\nconst packageJson = requi"
},
{
"path": "jest.config.js",
"chars": 646,
"preview": "// For a detailed explanation regarding each configuration property, visit:\n// https://jestjs.io/docs/en/configuration.h"
},
{
"path": "package.json",
"chars": 1807,
"preview": "{\n \"name\": \"tasksfile\",\n \"version\": \"5.1.1\",\n \"description\": \"Minimalistic task runner for node.js\",\n \"keywords\": [\n"
},
{
"path": "src/index.spec.ts",
"chars": 2124,
"preview": "import { shell } from '@pawelgalazka/shell'\nimport chalk from 'chalk'\n\nimport { sh } from './index'\n\nconst shellMock = s"
},
{
"path": "src/index.ts",
"chars": 2001,
"preview": "import {\n cli as cliEngine,\n CLIError,\n CommandsModule,\n Middleware,\n useMiddlewares\n} from '@pawelgalazka/cli'\nimp"
},
{
"path": "test/__snapshots__/e2e.spec.ts.snap",
"chars": 349,
"preview": "// Jest Snapshot v1, https://goo.gl/fbAQLP\n\nexports[`tasksfile displays commands list if only --help option provided and"
},
{
"path": "test/e2e.spec.ts",
"chars": 2673,
"preview": "/* eslint-env jest */\nimport { execSync as orgExecSync } from 'child_process'\n\ndescribe('tasksfile', () => {\n const scr"
},
{
"path": "test/sandbox/package.json",
"chars": 119,
"preview": "{\n \"name\": \"sandbox\",\n \"private\": true,\n \"version\": \"1.0.0\",\n \"scripts\": {\n \"task\": \"node ./tasksfile.js\"\n }\n}\n"
},
{
"path": "test/sandbox/scripts/color.js",
"chars": 92,
"preview": "const chalk = require('chalk')\n\nconsole.log(chalk.yellow('This should be in yellow color'))\n"
},
{
"path": "test/sandbox/scripts/error.js",
"chars": 33,
"preview": "throw new Error('error message')\n"
},
{
"path": "test/sandbox/scripts/hello.js",
"chars": 43,
"preview": "#!/usr/bin/env node\n\nconsole.log('Hello!')\n"
},
{
"path": "test/sandbox/tasksfile.js",
"chars": 1342,
"preview": "const { sh, help, cli } = require('../../lib')\n\nhelp(echo, 'Simple echo task')\n\nfunction echo(...args) {\n console.log('"
},
{
"path": "tsconfig.json",
"chars": 1890,
"preview": "{\n \"compilerOptions\": {\n /* Basic Options */\n \"target\": \"es2015\", /* Specify ECMAScript "
},
{
"path": "tslint.json",
"chars": 322,
"preview": "{\n \"extends\": [\n \"tslint:latest\", \"tslint-config-prettier\"\n ],\n \"rules\": {\n \"prettier\": true,\n \"max-cl"
}
]
About this extraction
This page contains the full source code of the pawelgalazka/runjs GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 24 files (31.1 KB), approximately 9.0k tokens, and a symbol index with 12 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.