Skip to content

Commit

Permalink
feat: add locator onlyFiles & onlyDirectories option (#469)
Browse files Browse the repository at this point in the history
* feat: add locator onlyFiles & onlyDirectories option

* feat: simplified patterns and path option building

* fix: locator-options-input type properties

* fix: locator-info extension might be undefinedÂ
  • Loading branch information
tada5hi authored Apr 2, 2024
1 parent baa379d commit 147e824
Show file tree
Hide file tree
Showing 7 changed files with 131 additions and 84 deletions.
5 changes: 4 additions & 1 deletion src/loader/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,10 @@ export class LoaderManager implements Loader {
for (let i = 0; i < this.rules.length; i++) {
const { test } = this.rules[i] as Rule;
if (Array.isArray(test)) {
if (test.indexOf(info.extension) !== -1) {
if (
info.extension &&
test.indexOf(info.extension) !== -1
) {
return this.rules[i].loader;
}
} else if (test.test(buildFilePath(info))) {
Expand Down
56 changes: 21 additions & 35 deletions src/locator/async.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,37 +6,30 @@
*/

import fg from 'fast-glob';
import type { LocatorInfo, LocatorOptions } from './type';
import { buildLocatorOptions, pathToLocatorInfo } from './utils';
import type { LocatorInfo, LocatorOptionsInput } from './types';
import { buildLocatorOptions, buildLocatorPatterns, pathToLocatorInfo } from './utils';

export async function locateMany(
pattern: string | string[],
options?: Partial<LocatorOptions>,
options?: LocatorOptionsInput,
) : Promise<LocatorInfo[]> {
options = buildLocatorOptions(options);

const patterns = Array.isArray(pattern) ?
pattern :
[pattern];

let ignore : string[] | undefined;
if (options.ignore) {
ignore = Array.isArray(options.ignore) ? options.ignore : [options.ignore];
}
const patterns = buildLocatorPatterns(pattern);
const opts = buildLocatorOptions(options);

const items : LocatorInfo[] = [];

for (let i = 0; i < patterns.length; i++) {
for (let j = 0; j < (options as LocatorOptions).path.length; j++) {
const files = await fg(patterns[i] as string, {
for (let j = 0; j < opts.path.length; j++) {
const files = await fg(patterns[i], {
absolute: true,
cwd: (options as LocatorOptions).path[j],
ignore,
onlyFiles: true,
cwd: opts.path[j],
ignore: opts.ignore,
onlyFiles: opts.onlyFiles,
onlyDirectories: opts.onlyDirectories,
});

for (let k = 0; k < files.length; k++) {
items.push(pathToLocatorInfo(files[k] as string, true));
items.push(pathToLocatorInfo(files[k], true));
}
}
}
Expand All @@ -46,26 +39,19 @@ export async function locateMany(

export async function locate(
pattern: string | string[],
options?: Partial<LocatorOptions>,
options?: LocatorOptionsInput,
) : Promise<LocatorInfo | undefined> {
options = buildLocatorOptions(options);

const patterns = Array.isArray(pattern) ?
pattern :
[pattern];

let ignore : string[] | undefined;
if (options.ignore) {
ignore = Array.isArray(options.ignore) ? options.ignore : [options.ignore];
}
const patterns = buildLocatorPatterns(pattern);
const opts = buildLocatorOptions(options);

for (let i = 0; i < patterns.length; i++) {
for (let j = 0; j < (options as LocatorOptions).path.length; j++) {
const files = await fg(patterns[i] as string, {
for (let j = 0; j < opts.path.length; j++) {
const files = await fg(patterns[i], {
absolute: true,
cwd: (options as LocatorOptions).path[j],
ignore,
onlyFiles: true,
cwd: opts.path[j],
ignore: opts.ignore,
onlyFiles: opts.onlyFiles,
onlyDirectories: opts.onlyDirectories,
});

const element = files.shift();
Expand Down
2 changes: 1 addition & 1 deletion src/locator/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@

export * from './async';
export * from './sync';
export * from './type';
export * from './types';
export * from './utils';
54 changes: 20 additions & 34 deletions src/locator/sync.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,37 +6,30 @@
*/

import fg from 'fast-glob';
import type { LocatorInfo, LocatorOptions } from './type';
import { buildLocatorOptions, pathToLocatorInfo } from './utils';
import type { LocatorInfo, LocatorOptionsInput } from './types';
import { buildLocatorOptions, buildLocatorPatterns, pathToLocatorInfo } from './utils';

export function locateManySync(
pattern: string | string[],
options?: Partial<LocatorOptions>,
options?: LocatorOptionsInput,
) : LocatorInfo[] {
options = buildLocatorOptions(options);

const patterns = Array.isArray(pattern) ?
pattern :
[pattern];

let ignore : string[] | undefined;
if (options.ignore) {
ignore = Array.isArray(options.ignore) ? options.ignore : [options.ignore];
}
const patterns = buildLocatorPatterns(pattern);
const opts = buildLocatorOptions(options);

const items : LocatorInfo[] = [];

for (let i = 0; i < patterns.length; i++) {
for (let j = 0; j < (options as LocatorOptions).path.length; j++) {
const files = fg.sync(patterns[i] as string, {
for (let j = 0; j < opts.path.length; j++) {
const files = fg.sync(patterns[i], {
absolute: true,
cwd: (options as LocatorOptions).path[j],
ignore,
onlyFiles: true,
cwd: opts.path[j],
ignore: opts.ignore,
onlyFiles: opts.onlyFiles,
onlyDirectories: opts.onlyDirectories,
});

for (let k = 0; k < files.length; k++) {
items.push(pathToLocatorInfo(files[k] as string, true));
items.push(pathToLocatorInfo(files[k], true));
}
}
}
Expand All @@ -46,26 +39,19 @@ export function locateManySync(

export function locateSync(
pattern: string | string[],
options?: Partial<LocatorOptions>,
options?: LocatorOptionsInput,
) : LocatorInfo | undefined {
options = buildLocatorOptions(options);

const patterns = Array.isArray(pattern) ?
pattern :
[pattern];

let ignore : string[] | undefined;
if (options.ignore) {
ignore = Array.isArray(options.ignore) ? options.ignore : [options.ignore];
}
const patterns = buildLocatorPatterns(pattern);
const opts = buildLocatorOptions(options);

for (let i = 0; i < patterns.length; i++) {
for (let j = 0; j < (options as LocatorOptions).path.length; j++) {
for (let j = 0; j < opts.path.length; j++) {
const files = fg.sync(patterns[i] as string, {
absolute: true,
cwd: (options as LocatorOptions).path[j],
ignore,
onlyFiles: true,
cwd: opts.path[j],
ignore: opts.ignore,
onlyFiles: opts.onlyFiles,
onlyDirectories: opts.onlyDirectories,
});

const element = files.shift();
Expand Down
13 changes: 10 additions & 3 deletions src/locator/type.ts → src/locator/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,17 @@
export type LocatorInfo = {
path: string,
name: string,
extension: string,
extension?: string
};

export type LocatorOptions = {
path: string | string[],
ignore: string | string[]
path: string[],
ignore: string[],
onlyFiles: boolean,
onlyDirectories: boolean
};

export type LocatorOptionsInput = Partial<Omit<LocatorOptions, 'path' | 'ignore'>> & {
path?: string | string[],
ignore?: string | string[],
};
49 changes: 39 additions & 10 deletions src/locator/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,47 @@

import path from 'node:path';
import { isObject, toArray } from '../utils';
import type { LocatorInfo, LocatorOptions } from './type';
import type { LocatorInfo, LocatorOptions, LocatorOptionsInput } from './types';

export function buildLocatorOptions(options?: Partial<LocatorOptions>) : LocatorOptions {
options = options || {};
export function buildLocatorPatterns(pattern: string | string[]) : string[] {
return Array.isArray(pattern) ?
pattern :
[pattern];
}

export function buildLocatorOptions(options: LocatorOptionsInput = {}) : LocatorOptions {
const paths = options.path ?
toArray(options.path) :
[];

options.path = options.path || [];
options.path = toArray(options.path);
if (options.path.length === 0) {
options.path.push(process.cwd());
const ignore = options.ignore ?
toArray(options.ignore) :
[];

if (paths.length === 0) {
paths.push(process.cwd());
}

options.ignore ??= [];
let onlyFiles : boolean;
let onlyDirectories : boolean;

if (options.onlyDirectories === options.onlyFiles) {
onlyDirectories = false;
onlyFiles = !options.onlyDirectories;
} else if (typeof options.onlyFiles === 'undefined') {
onlyDirectories = options.onlyDirectories ?? false;
onlyFiles = !options.onlyDirectories;
} else {
onlyFiles = options.onlyFiles ?? true;
onlyDirectories = !options.onlyFiles;
}

return options as LocatorOptions;
return {
path: paths,
ignore,
onlyDirectories,
onlyFiles,
};
}

export function pathToLocatorInfo(
Expand All @@ -39,7 +66,9 @@ export function pathToLocatorInfo(
return {
path: info.dir.split('/').join(path.sep),
name: info.name,
extension: info.ext,
extension: info.ext ?
info.ext :
undefined,
};
}

Expand Down
36 changes: 36 additions & 0 deletions test/unit/locator.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,42 @@ import type { LocatorInfo } from '../../src';
const basePath = path.join(__dirname, '..', 'data');

describe('src/locator.ts', () => {
it('should locate directory', async () => {
let locatorInfo = await locate(['data'], {
onlyDirectories: true,
path: path.join(__dirname, '..'),
});
expect(locatorInfo).toBeDefined();
if (locatorInfo) {
expect(locatorInfo.name).toEqual('data');
}

locatorInfo = locateSync(['unit'], {
onlyDirectories: true,
path: path.join(__dirname, '..'),
});
expect(locatorInfo).toBeDefined();
if (locatorInfo) {
expect(locatorInfo.name).toEqual('unit');
}
});

it('should locate directories', async () => {
let locatorInfo = await locateMany(['*'], {
onlyDirectories: true,
path: path.join(__dirname, '..'),
});
expect(locatorInfo.length).toEqual(2);
expect(locatorInfo.map((el) => el.name)).toEqual(['data', 'unit']);

locatorInfo = locateManySync(['*'], {
onlyDirectories: true,
path: path.join(__dirname, '..'),
});
expect(locatorInfo.length).toEqual(2);
expect(locatorInfo.map((el) => el.name)).toEqual(['data', 'unit']);
});

it('should locate .[cm]js file', async () => {
let locatorInfo = await locate(['file.[cf]js'], { path: [basePath] });
expect(locatorInfo).toBeDefined();
Expand Down

0 comments on commit 147e824

Please sign in to comment.