Skip to content
Merged
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
19 changes: 10 additions & 9 deletions commands/__tests__/lint.test.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
// @ts-nocheck
import yargs from 'yargs';
import yargs, { Argv } from 'yargs';
import { addConfigOptions, addAccountOptions } from '../../lib/commonOpts';
import lintCommand from '../lint';

jest.mock('yargs');
jest.mock('../../lib/commonOpts');

// Import this last so mocks apply
import lintCommand from '../lint';
const positionalSpy = jest
.spyOn(yargs as Argv, 'positional')
.mockReturnValue(yargs as Argv);

describe('commands/lint', () => {
describe('command', () => {
Expand All @@ -17,23 +18,23 @@ describe('commands/lint', () => {

describe('describe', () => {
it('should not provide a description', () => {
expect(lintCommand.describe).toEqual(null);
expect(lintCommand.describe).toEqual(undefined);
});
});

describe('builder', () => {
it('should support the correct positional arguments', () => {
lintCommand.builder(yargs);
lintCommand.builder(yargs as Argv);

expect(yargs.positional).toHaveBeenCalledTimes(1);
expect(yargs.positional).toHaveBeenCalledWith(
expect(positionalSpy).toHaveBeenCalledTimes(1);
expect(positionalSpy).toHaveBeenCalledWith(
'path',
expect.objectContaining({ type: 'string' })
);
});

it('should support the correct options', () => {
lintCommand.builder(yargs);
lintCommand.builder(yargs as Argv);

expect(addConfigOptions).toHaveBeenCalledTimes(1);
expect(addConfigOptions).toHaveBeenCalledWith(yargs);
Expand Down
84 changes: 48 additions & 36 deletions commands/lint.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,27 @@
// @ts-nocheck
const { lint } = require('@hubspot/local-dev-lib/cms/validate');
const { logger } = require('@hubspot/local-dev-lib/logger');
import { Argv, ArgumentsCamelCase } from 'yargs';
import { lint } from '@hubspot/local-dev-lib/cms/validate';
import { logger } from '@hubspot/local-dev-lib/logger';
import {
HubLValidationError,
LintResult,
Validation,
} from '@hubspot/local-dev-lib/types/HublValidation';
const { logError } = require('../lib/errorHandlers/index');
const {
addConfigOptions,
addAccountOptions,
addGlobalOptions,
} = require('../lib/commonOpts');
const { resolveLocalPath } = require('../lib/filesystem');
const { trackCommandUsage } = require('../lib/usageTracking');
const { i18n } = require('../lib/lang');

const { EXIT_CODES } = require('../lib/enums/exitCodes');

export const command = 'lint <path>';
import { logError } from '../lib/errorHandlers/index';
import { trackCommandUsage } from '../lib/usageTracking';
import { i18n } from '../lib/lang';
import { resolveLocalPath } from '../lib/filesystem';
import { EXIT_CODES } from '../lib/enums/exitCodes';
import {
AccountArgs,
CommonArgs,
ConfigArgs,
YargsCommandModule,
} from '../types/Yargs';
import { makeYargsBuilder } from '../lib/yargsUtils';

const command = 'lint <path>';
// Hiding since this command is still experimental
export const describe = null; //'Lint a file or folder for HubL syntax';
const describe = undefined; //'Lint a file or folder for HubL syntax';

function getErrorsFromHublValidationObject(
validation: Validation
Expand All @@ -30,7 +31,7 @@ function getErrorsFromHublValidationObject(
);
}

function printHublValidationError(err: HubLValidationError) {
function printHublValidationError(err: HubLValidationError): void {
const { severity, message, lineno, startPosition } = err;
const method = severity === 'FATAL' ? 'error' : 'warn';
logger[method]('[%d, %d]: %s', lineno, startPosition, message);
Expand Down Expand Up @@ -59,50 +60,61 @@ function printHublValidationResult({ file, validation }: LintResult): number {
return count;
}

export const handler = async options => {
const { path: lintPath } = options;
type LintArgs = CommonArgs & ConfigArgs & AccountArgs & { path: string };

async function handler(args: ArgumentsCamelCase<LintArgs>): Promise<void> {
const { path: lintPath, derivedAccountId } = args;

const { derivedAccountId } = options;
const localPath = resolveLocalPath(lintPath);
const groupName = i18n(`commands.lint.groupName`, {
path: localPath,
});

trackCommandUsage('lint', null, derivedAccountId);
trackCommandUsage('lint', undefined, derivedAccountId);

logger.group(groupName);
let count = 0;
try {
await lint(derivedAccountId, localPath, result => {
count += printHublValidationResult(result);
await lint(derivedAccountId, localPath, (result: LintResult) => {
return (count += printHublValidationResult(result));
});
} catch (err) {
logger.groupEnd(groupName);
logger.groupEnd();
logError(err, { accountId: derivedAccountId });
process.exit(EXIT_CODES.ERROR);
}
logger.groupEnd(groupName);
logger.groupEnd();
logger.log(
i18n(`commands.lint.issuesFound`, {
count,
})
);
};
}

export const builder = yargs => {
addConfigOptions(yargs);
addAccountOptions(yargs);
addGlobalOptions(yargs);
function lintBuilder(yargs: Argv): Argv<LintArgs> {
yargs.positional('path', {
describe: i18n(`commands.lint.positionals.path.describe`),
required: true,
type: 'string',
});
return yargs;
};

module.exports = {
builder,
handler,
return yargs as Argv<LintArgs>;
}

const builder = makeYargsBuilder<LintArgs>(lintBuilder, command, describe, {
useGlobalOptions: true,
useConfigOptions: true,
useAccountOptions: true,
});

const lintCommand: YargsCommandModule<unknown, LintArgs> = {
command,
describe,
handler,
builder,
};

export default lintCommand;

// TODO Remove this after cli.ts is ported to TS
module.exports = lintCommand;