Skip to content

Commit

Permalink
Merge pull request #83 from YuriSS/feat/allow-change-group-order
Browse files Browse the repository at this point in the history
feat: allow changing the groups order
  • Loading branch information
nivekcode authored Jul 1, 2022
2 parents 815f518 + 6569138 commit 9e04342
Show file tree
Hide file tree
Showing 10 changed files with 107 additions and 11 deletions.
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,13 @@ import-conductor -p @customA @customB
import-conductor --separator '' ==> no separator
```

- `groupOrder` - The group order to follow: (defaults to `[thirdParty, userLibrary, differentModule, sameModule]`)

```shell script
import-conductor --groupOrder 'userLibrary' 'differentModule' 'sameModule' 'thirdParty'
import-conductor -g 'userLibrary' 'differentModule' 'sameModule' 'thirdParty'
```

- `staged` - Run against staged files: (defaults to `false`)

```shell script
Expand Down
42 changes: 41 additions & 1 deletion __tests__/optimize-imports-mocks.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export type TestCase = { input: string; expected: string; noOfRuns?: number };
export type TestCase = { input: string; expected: string; noOfRuns?: number; groupOrder?: string[] };

export const readmeExample: TestCase = {
input: `import fs from 'fs';
Expand Down Expand Up @@ -111,3 +111,43 @@ import { MatDialogRef } from '@angular/material/dialog';
import { Observable } from 'rxjs';
import { AboutDialogBloc, AboutState } from './about-dialog.bloc';`,
};

export const noImportStatement: TestCase = {
input: `const x = 2;`,
expected: `const x = 2;`,
};

export const importsOnDifferentGroupOrder: TestCase = {
groupOrder: ['userLibrary', 'sameModule', 'differentModule', 'thirdParty'],
input: `import { Component } from '@angular/core';
import fs from 'fs';
import { LoggerService } from '@myorg/logger';
import { Order } from '../order/order.model';
import { CustomService } from './customer.service';`,
expected: `import { LoggerService } from '@myorg/logger';
import { CustomService } from './customer.service';
import { Order } from '../order/order.model';
import { Component } from '@angular/core';
import fs from 'fs';`,
};

export const importsWithGroupOrderIncorrect: TestCase = {
groupOrder: ['userLibrary', 'differentModule', 'thirdParty'],
input: `import fs from 'fs';
import { CustomerService } from './customer.service';
import { Order } from '../order/order.model';
import { Component, OnInit } from '@angular/core';
import { LoggerService } from '@myorg/logger';
import { Observable } from 'rxjs';
import { spawn } from 'child_process';`,
expected: `import { Component, OnInit } from '@angular/core';
import { spawn } from 'child_process';
import fs from 'fs';
import { Observable } from 'rxjs';
import { LoggerService } from '@myorg/logger';
import { Order } from '../order/order.model';
import { CustomerService } from './customer.service';`,
};
30 changes: 29 additions & 1 deletion __tests__/optimize-imports.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,18 @@ import { actions, organizeImports, organizeImportsForFile } from '@ic/conductor/
import * as config from '@ic/config';
import fs from 'fs';
import { Config } from '@ic/types';
import { readmeExample, comments, TestCase, codeBetweenImports, emptyNewLineSeparator } from './optimize-imports-mocks';
import {
readmeExample,
comments,
TestCase,
codeBetweenImports,
emptyNewLineSeparator,
noImportStatement,
importsOnDifferentGroupOrder,
importsWithGroupOrderIncorrect,
} from './optimize-imports-mocks';
import { defaultConfig } from '@ic/defaultConfig';
import { getGroupOrder } from '@ic/conductor/get-group-order';

jest.mock('fs');
jest.mock('simple-git');
Expand Down Expand Up @@ -72,4 +82,22 @@ describe('optimizeImports', () => {
expect(fs.writeFileSync).not.toHaveBeenCalled();
}
});

it('should do nothing if the file has no import', async () => {
(fs.readFileSync as any).mockReturnValue(Buffer.from(noImportStatement.input));
const file = 'test.ts';
const result = await organizeImportsForFile(file);
expect(result).toBe(actions.none);
expect(fs.writeFileSync).not.toHaveBeenCalled();
});

it('should change group order', async () => {
spy.and.returnValue({ ...basicConfig, groupOrder: importsOnDifferentGroupOrder.groupOrder, separator: '' });
await assertConductor(importsOnDifferentGroupOrder);
});

it('should use default order because incorrect group order input', async () => {
spy.and.returnValue({ ...basicConfig, groupOrder: getGroupOrder({ groupOrder: importsWithGroupOrderIncorrect.groupOrder }) });
await assertConductor(importsWithGroupOrderIncorrect);
});
});
7 changes: 7 additions & 0 deletions src/cliOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,13 @@ export const optionDefinitions = [
multiple: true,
description: 'The prefix of custom user libraries',
},
{
name: 'groupOrder',
alias: 'g',
type: String,
multiple: true,
description: 'The group order it should follow',
},
{
name: 'staged',
type: Boolean,
Expand Down
8 changes: 3 additions & 5 deletions src/conductor/format-import-statements.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,11 @@ import { ImportCategories } from '../types';

type CategoryEntry = [string, Map<string, string>];

const categoriesOrder = ['thirdParty', 'userLibrary', 'differentModule', 'sameModule'];

export function formatImportStatements(importCategories: ImportCategories, lineEnding: string) {
const { separator } = getConfig();
const [first, ...otherCategories] = Object.entries(importCategories)
.filter(hasImports)
.sort(byCategoriesOrder)
.sort(byCategoriesOrder(getConfig().groupOrder))
.map((imports) => toImportBlock(imports, lineEnding));

let result = first || '';
Expand All @@ -21,8 +19,8 @@ export function formatImportStatements(importCategories: ImportCategories, lineE
return result;
}

function byCategoriesOrder([a]: CategoryEntry, [b]: CategoryEntry): number {
return categoriesOrder.indexOf(a) - categoriesOrder.indexOf(b);
function byCategoriesOrder(categoriesOrder: string[]) {
return ([a]: CategoryEntry, [b]: CategoryEntry): number => categoriesOrder.indexOf(a) - categoriesOrder.indexOf(b);
}

function hasImports([, imports]: CategoryEntry) {
Expand Down
12 changes: 12 additions & 0 deletions src/conductor/get-group-order.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { defaultConfig } from '../defaultConfig';
import { Config } from '../types';

export function getGroupOrder(config: Partial<Config>) {
const groups = new Set(config?.groupOrder || []);
const uniqueGroups = Array.from(groups);
return isValidGroupArgument(uniqueGroups) ? uniqueGroups : defaultConfig.groupOrder;
}

function isValidGroupArgument(groups: string[]): boolean {
return groups.length === defaultConfig.groupOrder.length && groups.every((group) => defaultConfig.groupOrder.includes(group));
}
8 changes: 4 additions & 4 deletions src/conductor/organize-imports.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ export async function organizeImportsForFile(filePath: string): Promise<string>
const { staged, autoAdd, dryRun } = getConfig();
const fileWithOrganizedImports = await organizeImports(fileContent);
const fileHasChanged = fileWithOrganizedImports !== fileContent;
const isValidAction = [actions.none, actions.skipped].every(action => action !== fileWithOrganizedImports);
const isValidAction = [actions.none, actions.skipped].every((action) => action !== fileWithOrganizedImports);

if (fileHasChanged && isValidAction) {
!dryRun && writeFileSync(filePath, fileWithOrganizedImports);
Expand All @@ -55,11 +55,11 @@ export async function organizeImportsForFile(filePath: string): Promise<string>
msg += ', added to git';
}
log('green', msg, filePath);
} else {
log('gray', 'no change needed', filePath);
return actions.reordered;
}

return fileHasChanged ? actions.reordered : actions.none;
log('gray', 'no change needed', filePath);
return actions.none;
}

export async function organizeImports(fileContent: string): Promise<string> {
Expand Down
2 changes: 2 additions & 0 deletions src/config.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { sync } from 'glob';

import { getGroupOrder } from './conductor/get-group-order';
import { getThirdParty } from './conductor/get-third-party';
import { defaultConfig } from './defaultConfig';
import { CliConfig, Config } from './types';
Expand All @@ -17,6 +18,7 @@ export function resolveConfig(cliConfig: Partial<CliConfig>): Config {
...defaultConfig,
...normalized,
thirdPartyDependencies: getThirdParty(),
groupOrder: getGroupOrder(normalized),
};
if (merged.ignore.length > 0) {
merged.ignore = merged.ignore.map((pattern) => (pattern.includes('*') ? sync(pattern) : pattern)).flat();
Expand Down
1 change: 1 addition & 0 deletions src/defaultConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@ export const defaultConfig: Config = {
staged: false,
dryRun: false,
ignore: [],
groupOrder: ['thirdParty', 'userLibrary', 'differentModule', 'sameModule'],
};
1 change: 1 addition & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export interface Config {
ignore: string[];
userLibPrefixes: string[];
thirdPartyDependencies?: Set<string>;
groupOrder: string[];
}

export type CliConfig = Omit<Config, 'autoAdd'> & { noAutoAdd: boolean };

0 comments on commit 9e04342

Please sign in to comment.