mirror of
https://github.com/Kong/insomnia.git
synced 2026-05-24 00:30:15 -04:00
CLI linting + exit codes (#2318)
This commit is contained in:
@@ -3,6 +3,7 @@ const mod = jest.requireActual('insomnia-testing');
|
||||
module.exports = {
|
||||
...mod,
|
||||
generate: jest.fn(),
|
||||
generateToFile: jest.fn(),
|
||||
runTests: jest.fn(),
|
||||
runTestsCli: jest.fn(),
|
||||
};
|
||||
|
||||
5
packages/insomnia-cli/flow-typed/@stoplight/spectral.js
vendored
Normal file
5
packages/insomnia-cli/flow-typed/@stoplight/spectral.js
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
// @flow
|
||||
|
||||
declare module '@stoplight/spectral' {
|
||||
declare module.exports: *;
|
||||
}
|
||||
947
packages/insomnia-cli/package-lock.json
generated
947
packages/insomnia-cli/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -37,6 +37,7 @@
|
||||
"rimraf": "^3.0.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"@stoplight/spectral": "^5.4.0",
|
||||
"commander": "^5.1.0",
|
||||
"insomnia-testing": "^2.2.9",
|
||||
"openapi-2-kong": "^2.2.10",
|
||||
|
||||
@@ -13,6 +13,7 @@ Options:
|
||||
Commands:
|
||||
generate Code generation utilities
|
||||
run Execution utilities
|
||||
lint Linting utilities
|
||||
help [command] display help for command"
|
||||
`;
|
||||
|
||||
@@ -29,6 +30,7 @@ Options:
|
||||
Commands:
|
||||
generate Code generation utilities
|
||||
run Execution utilities
|
||||
lint Linting utilities
|
||||
help [command] display help for command"
|
||||
`;
|
||||
|
||||
@@ -70,9 +72,32 @@ Options:
|
||||
Commands:
|
||||
generate Code generation utilities
|
||||
run Execution utilities
|
||||
lint Linting utilities
|
||||
help [command] display help for command"
|
||||
`;
|
||||
|
||||
exports[`Snapshot for "inso lint -h" 1`] = `
|
||||
"Usage: inso lint [options] [command]
|
||||
|
||||
Linting utilities
|
||||
|
||||
Options:
|
||||
-h, --help display help for command
|
||||
|
||||
Commands:
|
||||
spec <identifier> Lint an API Specification
|
||||
help [command] display help for command"
|
||||
`;
|
||||
|
||||
exports[`Snapshot for "inso lint spec -h" 1`] = `
|
||||
"Usage: inso lint spec [options] <identifier>
|
||||
|
||||
Lint an API Specification
|
||||
|
||||
Options:
|
||||
-h, --help display help for command"
|
||||
`;
|
||||
|
||||
exports[`Snapshot for "inso run -h" 1`] = `
|
||||
"Usage: inso run [options] [command]
|
||||
|
||||
@@ -95,5 +120,6 @@ Options:
|
||||
-r, --reporter <reporter> reporter to use, options are [dot, list, spec,
|
||||
min, progress] (default: \\"spec\\")
|
||||
-b, --bail abort (\\"bail\\") after first test failure
|
||||
--keep-file do not delete the generated test file
|
||||
-h, --help display help for command"
|
||||
`;
|
||||
|
||||
@@ -3,7 +3,6 @@ import * as cli from '../cli';
|
||||
import { generateConfig } from '../commands/generate-config';
|
||||
|
||||
jest.mock('../commands/generate-config');
|
||||
const originalError = console.error;
|
||||
|
||||
const initInso = () => {
|
||||
return (args: string): void => {
|
||||
@@ -21,11 +20,13 @@ describe('cli', () => {
|
||||
let inso = initInso();
|
||||
beforeEach(() => {
|
||||
inso = initInso();
|
||||
(console: any).error = jest.fn();
|
||||
jest.spyOn(console, 'error').mockImplementation(() => {});
|
||||
jest.spyOn(process, 'exit').mockImplementation(() => {});
|
||||
(generateConfig: any).mockResolvedValue(true);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
(console: any).error = originalError;
|
||||
jest.restoreAllMocks();
|
||||
});
|
||||
|
||||
it('should error when required --type option is missing', () =>
|
||||
|
||||
@@ -7,7 +7,17 @@ import * as packageJson from '../../package.json';
|
||||
// These tests use the executable /bin/inso, which relies on /dist.
|
||||
|
||||
describe('Snapshot for', () => {
|
||||
it.each(['-h', '--help', 'help', 'generate -h', 'generate config -h', 'run -h', 'run test -h'])(
|
||||
it.each([
|
||||
'-h',
|
||||
'--help',
|
||||
'help',
|
||||
'generate -h',
|
||||
'generate config -h',
|
||||
'run -h',
|
||||
'run test -h',
|
||||
'lint -h',
|
||||
'lint spec -h',
|
||||
])(
|
||||
'"inso %s"',
|
||||
async args => {
|
||||
const { stdout } = await execa(getBinPathSync(), args.split(' '));
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// @flow
|
||||
import commander from 'commander';
|
||||
import { getAllOptions } from '../util';
|
||||
import { getAllOptions, exit, logErrorExit1 } from '../util';
|
||||
|
||||
describe('getAllOptions()', () => {
|
||||
it('should combine options from all commands into one object', () => {
|
||||
@@ -21,3 +21,45 @@ describe('getAllOptions()', () => {
|
||||
parent.parse('node test command subCommand --global --subCmd'.split(' '));
|
||||
});
|
||||
});
|
||||
|
||||
describe('exit()', () => {
|
||||
it('should exit 0 if successful result', async () => {
|
||||
const exitSpy = jest.spyOn(process, 'exit').mockImplementation(() => {});
|
||||
|
||||
await exit(new Promise(resolve => resolve(true)));
|
||||
|
||||
expect(exitSpy).toHaveBeenCalledWith(0);
|
||||
});
|
||||
|
||||
it('should exit 1 if unsuccessful result', async () => {
|
||||
const exitSpy = jest.spyOn(process, 'exit').mockImplementation(() => {});
|
||||
|
||||
await exit(new Promise(resolve => resolve(false)));
|
||||
|
||||
expect(exitSpy).toHaveBeenCalledWith(1);
|
||||
});
|
||||
|
||||
it('should exit 1 and print to console and if rejected', async () => {
|
||||
const exitSpy = jest.spyOn(process, 'exit').mockImplementation(() => {});
|
||||
const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
|
||||
|
||||
const error = new Error('message');
|
||||
await exit(new Promise((resolve, reject) => reject(error)));
|
||||
|
||||
expect(errorSpy).toHaveBeenCalledWith(error);
|
||||
expect(exitSpy).toHaveBeenCalledWith(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('logErrorExit1()', () => {
|
||||
it('should exit 1 and print error to console', async () => {
|
||||
const exitSpy = jest.spyOn(process, 'exit').mockImplementation(() => {});
|
||||
const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
|
||||
|
||||
const error = new Error('message');
|
||||
await logErrorExit1(error);
|
||||
|
||||
expect(errorSpy).toHaveBeenCalledWith(error);
|
||||
expect(exitSpy).toHaveBeenCalledWith(1);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
// @flow
|
||||
import { ConversionTypeMap, generateConfig } from './commands/generate-config';
|
||||
import { getVersion, createCommand, getAllOptions } from './util';
|
||||
import { getVersion, createCommand, getAllOptions, logErrorExit1, exit } from './util';
|
||||
import { runInsomniaTests, TestReporterEnum } from './commands/run-tests';
|
||||
import { lintSpecification } from './commands/lint-specification';
|
||||
|
||||
function makeGenerateCommand(exitOverride: boolean) {
|
||||
// inso generate
|
||||
@@ -18,7 +19,7 @@ function makeGenerateCommand(exitOverride: boolean) {
|
||||
`type of configuration to generate, options are [${conversionTypes}]`,
|
||||
)
|
||||
.option('-o, --output <path>', 'save the generated config to a file')
|
||||
.action((identifier, cmd) => generateConfig(identifier, getAllOptions(cmd)));
|
||||
.action((identifier, cmd) => exit(generateConfig(identifier, getAllOptions(cmd))));
|
||||
|
||||
return generate;
|
||||
}
|
||||
@@ -39,11 +40,25 @@ function makeTestCommand(exitOverride: boolean) {
|
||||
TestReporterEnum.spec,
|
||||
)
|
||||
.option('-b, --bail', 'abort ("bail") after first test failure')
|
||||
.action(cmd => runInsomniaTests(getAllOptions(cmd)));
|
||||
.option('--keep-file', 'do not delete the generated test file')
|
||||
.action(cmd => exit(runInsomniaTests(getAllOptions(cmd))));
|
||||
|
||||
return run;
|
||||
}
|
||||
|
||||
function makeLintCommand(exitOverride: boolean) {
|
||||
// inso lint
|
||||
const lint = createCommand(exitOverride, 'lint').description('Linting utilities');
|
||||
|
||||
// inso lint spec
|
||||
lint
|
||||
.command('spec <identifier>')
|
||||
.description('Lint an API Specification')
|
||||
.action((identifier, cmd) => exit(lintSpecification(identifier, getAllOptions(cmd))));
|
||||
|
||||
return lint;
|
||||
}
|
||||
|
||||
export function go(args?: Array<string>, exitOverride?: boolean): void {
|
||||
if (!args) {
|
||||
args = process.argv;
|
||||
@@ -56,6 +71,7 @@ export function go(args?: Array<string>, exitOverride?: boolean): void {
|
||||
.option('--working-dir <dir>', 'set working directory')
|
||||
.addCommand(makeGenerateCommand(!!exitOverride))
|
||||
.addCommand(makeTestCommand(!!exitOverride))
|
||||
.addCommand(makeLintCommand(!!exitOverride))
|
||||
.parseAsync(args)
|
||||
.catch(err => console.log('An error occurred', err));
|
||||
.catch(logErrorExit1);
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ describe('generateConfig()', () => {
|
||||
|
||||
it('should write generated documents to file system', async () => {
|
||||
const consoleSpy = jest.spyOn(console, 'log').mockImplementation(() => {});
|
||||
const writeFileSpy = jest.spyOn(fs, 'writeFileSync').mockImplementation(() => {});
|
||||
const writeFileSpy = jest.spyOn(fs.promises, 'writeFile').mockImplementation(() => {});
|
||||
mock(o2k.generate).mockResolvedValue({ documents: ['a', 'b'] });
|
||||
|
||||
await generateConfig(filePath, { ...base, output: 'output.yaml' });
|
||||
@@ -69,7 +69,7 @@ describe('generateConfig()', () => {
|
||||
|
||||
it('should generate documents using workingDir', async () => {
|
||||
const consoleSpy = jest.spyOn(console, 'log').mockImplementation(() => {});
|
||||
const writeFileSpy = jest.spyOn(fs, 'writeFileSync').mockImplementation(() => {});
|
||||
const writeFileSpy = jest.spyOn(fs.promises, 'writeFile').mockImplementation(() => {});
|
||||
mock(o2k.generate).mockResolvedValue({ documents: ['a', 'b'] });
|
||||
|
||||
await generateConfig('file.yaml', {
|
||||
@@ -0,0 +1,20 @@
|
||||
// @flow
|
||||
import { lintSpecification } from '../lint-specification';
|
||||
|
||||
describe('lint specification', () => {
|
||||
it('should return true for linting passed', async () => {
|
||||
const result = await lintSpecification('spc_46c5a4a40e83445a9bd9d9758b86c16c', {
|
||||
workingDir: 'src/db/__fixtures__/git-repo',
|
||||
});
|
||||
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false for linting failed', async () => {
|
||||
const result = await lintSpecification('spc_46c5a4a40e83445a9bd9d9758b86c16c', {
|
||||
workingDir: 'src/db/__fixtures__/git-repo-malformed-spec',
|
||||
});
|
||||
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
});
|
||||
@@ -7,7 +7,12 @@ import type { RunTestsOptions } from '../run-tests';
|
||||
|
||||
jest.mock('insomnia-testing');
|
||||
jest.mock('os');
|
||||
jest.mock('console');
|
||||
jest.mock('fs', () => ({
|
||||
promises: {
|
||||
mkdir: jest.fn(),
|
||||
unlink: jest.fn(),
|
||||
},
|
||||
}));
|
||||
|
||||
describe('runInsomniaTests()', () => {
|
||||
// make flow happy
|
||||
@@ -39,9 +44,25 @@ describe('runInsomniaTests()', () => {
|
||||
const contents = 'generated test contents';
|
||||
mock(insomniaTesting.generate).mockResolvedValue(contents);
|
||||
|
||||
const options = { ...base, reporter: 'min', bail: true };
|
||||
const options = { ...base, reporter: 'min', bail: true, keepFile: false };
|
||||
await runInsomniaTests(options);
|
||||
|
||||
expect(insomniaTesting.runTestsCli).toHaveBeenCalledWith(contents, options);
|
||||
});
|
||||
|
||||
it('should return false if test results have any failures', async function() {
|
||||
mock(insomniaTesting.runTestsCli).mockResolvedValue(false);
|
||||
|
||||
const result = await runInsomniaTests(base);
|
||||
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
|
||||
it('should return true if test results have no failures', async function() {
|
||||
mock(insomniaTesting.runTestsCli).mockResolvedValue(true);
|
||||
|
||||
const result = await runInsomniaTests(base);
|
||||
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -11,10 +11,10 @@ export const ConversionTypeMap: { [string]: ConversionResultType } = {
|
||||
declarative: 'kong-declarative-config',
|
||||
};
|
||||
|
||||
export type GenerateConfigOptions = GlobalOptions<{|
|
||||
export type GenerateConfigOptions = GlobalOptions & {
|
||||
type: $Keys<typeof ConversionTypeMap>,
|
||||
output?: string,
|
||||
|}>;
|
||||
};
|
||||
|
||||
function validateOptions({ type }: GenerateConfigOptions): boolean {
|
||||
if (!ConversionTypeMap[type]) {
|
||||
@@ -29,9 +29,9 @@ function validateOptions({ type }: GenerateConfigOptions): boolean {
|
||||
export async function generateConfig(
|
||||
identifier: string,
|
||||
options: GenerateConfigOptions,
|
||||
): Promise<void> {
|
||||
): Promise<boolean> {
|
||||
if (!validateOptions(options)) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
const { type, output } = options;
|
||||
@@ -44,17 +44,13 @@ export async function generateConfig(
|
||||
|
||||
// try get from db
|
||||
const specFromDb = db.ApiSpec.get(identifier);
|
||||
try {
|
||||
if (specFromDb?.contents) {
|
||||
result = await o2k.generateFromString(specFromDb.contents, ConversionTypeMap[type]);
|
||||
} else {
|
||||
// try load as a file
|
||||
const fileName = path.join(workingDir, identifier);
|
||||
result = await o2k.generate(fileName, ConversionTypeMap[type]);
|
||||
}
|
||||
} catch (err) {
|
||||
console.log('Config failed to generate:', err.message);
|
||||
return;
|
||||
|
||||
if (specFromDb?.contents) {
|
||||
result = await o2k.generateFromString(specFromDb.contents, ConversionTypeMap[type]);
|
||||
} else {
|
||||
// try load as a file
|
||||
const fileName = path.join(workingDir, identifier);
|
||||
result = await o2k.generate(fileName, ConversionTypeMap[type]);
|
||||
}
|
||||
|
||||
const yamlDocs = result.documents.map(d => YAML.stringify(d));
|
||||
@@ -64,8 +60,10 @@ export async function generateConfig(
|
||||
|
||||
if (output) {
|
||||
const fullOutputPath = path.join(workingDir, output);
|
||||
fs.writeFileSync(fullOutputPath, document);
|
||||
await fs.promises.writeFile(fullOutputPath, document);
|
||||
} else {
|
||||
console.log(document);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
30
packages/insomnia-cli/src/commands/lint-specification.js
Normal file
30
packages/insomnia-cli/src/commands/lint-specification.js
Normal file
@@ -0,0 +1,30 @@
|
||||
// @flow
|
||||
|
||||
import { Spectral } from '@stoplight/spectral';
|
||||
import type { GlobalOptions } from '../util';
|
||||
import { gitDataDirDb } from '../db/mem-db';
|
||||
|
||||
export type LintSpecificationOptions = GlobalOptions;
|
||||
|
||||
export async function lintSpecification(
|
||||
identifier: string,
|
||||
options: LintSpecificationOptions,
|
||||
): Promise<boolean> {
|
||||
const { workingDir } = options;
|
||||
|
||||
const db = await gitDataDirDb({ dir: workingDir, filterTypes: ['ApiSpec'] });
|
||||
|
||||
const specFromDb = db.ApiSpec.get(identifier);
|
||||
|
||||
const spectral = new Spectral();
|
||||
const results = await spectral.run(specFromDb?.contents);
|
||||
|
||||
if (results.length) {
|
||||
results.forEach(r =>
|
||||
console.log(`${r.range.start.line}:${r.range.start.character} - ${r.message}`),
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -11,10 +11,11 @@ export const TestReporterEnum = {
|
||||
progress: 'progress',
|
||||
};
|
||||
|
||||
export type RunTestsOptions = GlobalOptions<{|
|
||||
export type RunTestsOptions = GlobalOptions & {
|
||||
reporter: $Keys<typeof TestReporterEnum>,
|
||||
bail?: boolean,
|
||||
|}>;
|
||||
keepFile?: boolean,
|
||||
};
|
||||
|
||||
function validateOptions({ reporter }: RunTestsOptions): boolean {
|
||||
if (reporter && !TestReporterEnum[reporter]) {
|
||||
@@ -31,7 +32,7 @@ export async function runInsomniaTests(options: RunTestsOptions): Promise<void>
|
||||
return;
|
||||
}
|
||||
|
||||
const { reporter, bail } = options;
|
||||
const { reporter, bail, keepFile } = options;
|
||||
|
||||
const suites = [
|
||||
{
|
||||
@@ -55,5 +56,5 @@ export async function runInsomniaTests(options: RunTestsOptions): Promise<void>
|
||||
];
|
||||
|
||||
const testFileContents = await generate(suites);
|
||||
await runTestsCli(testFileContents, { reporter, bail });
|
||||
return await runTestsCli(testFileContents, { reporter, bail, keepFile });
|
||||
}
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
_id: spc_46c5a4a40e83445a9bd9d9758b86c16c
|
||||
contentType: yaml
|
||||
contents: |
|
||||
openapi: '3.0.2'
|
||||
info:
|
||||
title: Global Security
|
||||
version: '1.2'
|
||||
servers:
|
||||
- url: https://api.server.test/v1
|
||||
tags:
|
||||
- name: Folder
|
||||
|
||||
paths:
|
||||
/global:
|
||||
get:
|
||||
tags:
|
||||
- Folder
|
||||
responses:
|
||||
'200':
|
||||
description: OK
|
||||
/override:
|
||||
get:
|
||||
security:
|
||||
- Key-Query: []
|
||||
responses:
|
||||
'200':
|
||||
description: OK
|
||||
created: 1589851906273
|
||||
fileName: Global Security
|
||||
modified: 1592254074772
|
||||
parentId: wrk_012d4860c7da418a85ffea7406e1292a
|
||||
type: ApiSpec
|
||||
@@ -0,0 +1,14 @@
|
||||
_id: env_ca046a738f001eb3090261a537b1b78f86c2094c
|
||||
color: null
|
||||
created: 1589851906358
|
||||
data:
|
||||
base_url: "{{ scheme }}://{{ host }}{{ base_path }}"
|
||||
dataPropertyOrder:
|
||||
"&":
|
||||
- base_url
|
||||
isPrivate: false
|
||||
metaSortKey: 1589851906358
|
||||
modified: 1592254074769
|
||||
name: Base environment
|
||||
parentId: wrk_012d4860c7da418a85ffea7406e1292a
|
||||
type: Environment
|
||||
@@ -0,0 +1,14 @@
|
||||
_id: env_env_ca046a738f001eb3090261a537b1b78f86c2094c_sub
|
||||
color: null
|
||||
created: 1592252904087
|
||||
data:
|
||||
base_path: /v1
|
||||
host: api.server.test
|
||||
scheme: https
|
||||
dataPropertyOrder: null
|
||||
isPrivate: false
|
||||
metaSortKey: 1592252904087
|
||||
modified: 1592254074767
|
||||
name: OpenAPI env
|
||||
parentId: env_ca046a738f001eb3090261a537b1b78f86c2094c
|
||||
type: Environment
|
||||
@@ -0,0 +1,21 @@
|
||||
_id: req_wrk_012d4860c7da418a85ffea7406e1292a21946b60
|
||||
authentication: {}
|
||||
body: {}
|
||||
created: 1592254074764
|
||||
description: ""
|
||||
headers: []
|
||||
isPrivate: false
|
||||
metaSortKey: -1592254074764
|
||||
method: GET
|
||||
modified: 1592254074764
|
||||
name: /global
|
||||
parameters: []
|
||||
parentId: fld_wrk_012d4860c7da418a85ffea7406e1292a30baa249
|
||||
settingDisableRenderRequestBody: false
|
||||
settingEncodeUrl: true
|
||||
settingFollowRedirects: global
|
||||
settingRebuildPath: true
|
||||
settingSendCookies: true
|
||||
settingStoreCookies: true
|
||||
type: Request
|
||||
url: "{{ base_url }}/global"
|
||||
@@ -0,0 +1,21 @@
|
||||
_id: req_wrk_012d4860c7da418a85ffea7406e1292ab410454b
|
||||
authentication: {}
|
||||
body: {}
|
||||
created: 1592254074762
|
||||
description: ""
|
||||
headers: []
|
||||
isPrivate: false
|
||||
metaSortKey: -1592254074762
|
||||
method: GET
|
||||
modified: 1592254074762
|
||||
name: /override
|
||||
parameters: []
|
||||
parentId: wrk_012d4860c7da418a85ffea7406e1292a
|
||||
settingDisableRenderRequestBody: false
|
||||
settingEncodeUrl: true
|
||||
settingFollowRedirects: global
|
||||
settingRebuildPath: true
|
||||
settingSendCookies: true
|
||||
settingStoreCookies: true
|
||||
type: Request
|
||||
url: "{{ base_url }}/override"
|
||||
@@ -0,0 +1,10 @@
|
||||
_id: fld_wrk_012d4860c7da418a85ffea7406e1292a30baa249
|
||||
created: 1592254074765
|
||||
description: ""
|
||||
environment: {}
|
||||
environmentPropertyOrder: null
|
||||
metaSortKey: -1592254074765
|
||||
modified: 1592254074765
|
||||
name: Folder
|
||||
parentId: wrk_012d4860c7da418a85ffea7406e1292a
|
||||
type: RequestGroup
|
||||
@@ -0,0 +1,8 @@
|
||||
_id: wrk_012d4860c7da418a85ffea7406e1292a
|
||||
created: 1589851906270
|
||||
description: ""
|
||||
modified: 1592254074771
|
||||
name: Global Security 1.2
|
||||
parentId: null
|
||||
scope: spec
|
||||
type: Workspace
|
||||
@@ -2,14 +2,14 @@
|
||||
import commander from 'commander';
|
||||
import * as packageJson from '../package.json';
|
||||
|
||||
export type GlobalOptions<T> = {|
|
||||
export type GlobalOptions = {
|
||||
workingDir?: string,
|
||||
...T,
|
||||
|};
|
||||
};
|
||||
|
||||
export function createCommand(exitOverride: boolean, cmd?: string) {
|
||||
const command = new commander.Command(cmd).storeOptionsAsProperties(false);
|
||||
|
||||
// TODO: can probably remove this
|
||||
if (exitOverride) {
|
||||
return command.exitOverride();
|
||||
}
|
||||
@@ -33,3 +33,13 @@ export function getAllOptions<T>(cmd: Object): T {
|
||||
|
||||
return opts;
|
||||
}
|
||||
|
||||
export function logErrorExit1(err: Error) {
|
||||
console.error(err);
|
||||
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
export async function exit(result: Promise<boolean>): Promise<void> {
|
||||
return result.then(r => process.exit(r ? 0 : 1)).catch(logErrorExit1);
|
||||
}
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
// @flow
|
||||
export { generate } from './src/generate';
|
||||
export { generate, generateToFile } from './src/generate';
|
||||
export { runTests, runTestsCli } from './src/run';
|
||||
|
||||
Reference in New Issue
Block a user