-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
10 changed files
with
205 additions
and
39 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
import path from 'path'; | ||
import fs from 'fs-extra'; | ||
import glob from 'glob'; | ||
import pify from 'pify'; | ||
import { parallel } from 'promist'; | ||
import { exists } from '~/utils/file'; | ||
import { FILE_NAME, FILE_EXT } from '~/constants'; | ||
import { IChild } from '../../types'; | ||
|
||
export default async function getChildrenFromGlobs( | ||
patterns: string[], | ||
directory: string | ||
): Promise<IChild[]> { | ||
const arrs = await parallel.map(patterns, (pattern) => | ||
fromGlob(pattern, directory) | ||
); | ||
|
||
const dirs = arrs.reduce((acc: string[], arr: string[]) => { | ||
return acc.concat(arr); | ||
}, []); | ||
|
||
// filter and make into IChild | ||
return filter(dirs).map((dir) => ({ | ||
// absolute path | ||
directory: path.join(directory, dir), | ||
matcher(name: string) { | ||
return dir.includes(name); | ||
} | ||
})); | ||
} | ||
|
||
export async function fromGlob( | ||
pattern: string, | ||
directory: string | ||
): Promise<string[]> { | ||
return parallel.filter( | ||
await pify(glob)(pattern, { cwd: directory }), | ||
async (dir: string) => { | ||
// get absolute path | ||
dir = path.join(directory, dir); | ||
|
||
// select only directories | ||
const stat = await fs.stat(dir); | ||
if (!stat.isDirectory()) return false; | ||
|
||
// select only directories that have a package.json | ||
// or a kpo configuration file | ||
const toFind = ['package.json'] | ||
.concat(FILE_EXT.map((ext) => FILE_NAME + ext)) | ||
.map((file) => path.join(dir, file)); | ||
|
||
for (let file of toFind) { | ||
if (await exists(file)) return true; | ||
} | ||
|
||
return false; | ||
} | ||
); | ||
} | ||
|
||
/** | ||
* Filter directories: select only the first one in depth | ||
* in which a configuration file was found. | ||
* If we have /foo and /foo/bar, only /foo will be selected | ||
*/ | ||
export function filter(dirs: string[]): string[] { | ||
dirs = dirs.sort(); | ||
let i = 1; | ||
while (i < dirs.length) { | ||
const current = dirs[i]; | ||
const previous = dirs[i - 1]; | ||
if (current.slice(0, previous.length) === previous) { | ||
dirs = dirs.slice(0, i).concat(dirs.slice(i + 1)); | ||
} else { | ||
i++; | ||
} | ||
} | ||
|
||
return dirs; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import path from 'path'; | ||
import { IOfType } from '~/types'; | ||
import { IChild } from '../../types'; | ||
|
||
export default function getChildrenFromMap( | ||
map: IOfType<string>, | ||
directory: string | ||
): IChild[] { | ||
return Object.entries(map).map(([key, value]) => ({ | ||
directory: path.isAbsolute(value) ? value : path.join(directory, value), | ||
matcher(name: string): boolean { | ||
return name === key; | ||
} | ||
})); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
import path from 'path'; | ||
import fs from 'fs-extra'; | ||
import logger from '~/utils/logger'; | ||
import { exists } from '~/utils/file'; | ||
import { rejects } from 'errorish'; | ||
import getChildrenFromGlobs from './from-globs'; | ||
import getChildrenFromMap from './from-map'; | ||
import { IChild } from '../../types'; | ||
import { TChildrenDefinition } from '~/types'; | ||
|
||
export default async function getChildren( | ||
directory: string, | ||
definition?: TChildrenDefinition | ||
): Promise<IChild[]> { | ||
logger.debug('obtaining children'); | ||
|
||
if (definition) { | ||
logger.debug('children found in options'); | ||
|
||
if (Array.isArray(definition)) { | ||
return getChildrenFromGlobs(definition, directory); | ||
} | ||
return getChildrenFromMap(definition, directory); | ||
} | ||
|
||
const lerna = (await exists(path.join(directory, 'lerna.json'))) | ||
? await fs.readJSON(path.join(directory, 'lerna.json')).catch(rejects) | ||
: null; | ||
|
||
if (lerna) { | ||
logger.debug('lerna file found'); | ||
if (lerna.packages) { | ||
return getChildrenFromGlobs(lerna.packages, directory); | ||
} | ||
} | ||
|
||
logger.debug('no children found'); | ||
return []; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import state from '../index'; | ||
import logger from '~/utils/logger'; | ||
import getChildren from './children'; | ||
import { IScopeDefinition } from '../types'; | ||
|
||
export default async function scope( | ||
scope: string | ||
): Promise<IScopeDefinition | null> { | ||
const paths = await state.paths(); | ||
|
||
// root scope | ||
if (scope === 'root') { | ||
if (paths.root) { | ||
return { names: ['root'], directory: paths.root.directory }; | ||
} else { | ||
logger.debug('root scope was not found and was assigned to self'); | ||
return null; | ||
} | ||
} | ||
|
||
// child scopes | ||
const children = await getChildren(paths.directory, state.get('children')); | ||
const matches = children | ||
.filter((child) => child.matcher(scope)) | ||
.map((child) => child.directory); | ||
|
||
if (matches.length) { | ||
logger.debug(`scopes found for ${scope}:\n${matches.join('\n')}`); | ||
|
||
if (matches.length > 1) { | ||
throw Error(`Several scopes matched name "${scope}"`); | ||
} | ||
|
||
return { names: [scope], directory: matches[0] }; | ||
} | ||
|
||
throw Error(`Scope ${scope} was not found`); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters