Skip to content

Commit

Permalink
feat: package functions and if-fn
Browse files Browse the repository at this point in the history
  • Loading branch information
Arcath committed Jul 7, 2021
1 parent dae6cd7 commit de48040
Show file tree
Hide file tree
Showing 7 changed files with 2,211 additions and 584 deletions.
2,521 changes: 1,943 additions & 578 deletions package-lock.json

Large diffs are not rendered by default.

13 changes: 7 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,17 @@
"@types/chalk": "^2.2.0",
"@types/jest": "^26.0.23",
"@types/left-pad": "^1.2.0",
"@types/node": "^15.12.4",
"jest": "^27.0.4",
"@types/node": "^16.0.0",
"jest": "^27.0.6",
"kcd-scripts": "^11.1.0",
"prettier": "^2.3.1",
"prettier": "^2.3.2",
"ts-jest": "^27.0.3",
"typedoc": "^0.21.0",
"typescript": "^4.3.4"
"typedoc": "^0.21.2",
"typescript": "^4.3.5"
},
"dependencies": {
"chalk": "^4.1.1"
"chalk": "^4.1.1",
"read-pkg-up": "^7.0.1"
},
"eslintConfig": {
"extends": "./node_modules/kcd-scripts/eslint.js",
Expand Down
25 changes: 25 additions & 0 deletions src/functions/if-fn.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import {ifFn, hasDevDependency} from '../index'

describe('If FN', () => {
it('should return the correct result', () => {
const testFn = ifFn((result: boolean) => result)

expect(testFn(true, 'pass', 'fail')).toBe('pass')
expect(testFn(false, 'fail', 'pass')).toBe('pass')

const ifDevDep = ifFn((dep: string) => {
return hasDevDependency(
{
name: 'sample',
version: '1.2.3',
readme: '',
_id: '1',
devDependencies: {react: '17.0.1'}
},
dep
)
})

expect(ifDevDep('react', true, false)).toBeTruthy()
})
})
24 changes: 24 additions & 0 deletions src/functions/if-fn.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/**
* Creates a one line true/false function
*
* ```ts
* const ifLongString = ifFn((s: string) => {
* return s.length > 10
* })
*
* ifLongString('short', 'yes', 'no') // 'no'
* ifLongString('Longer string that is long', 'yes', 'no') // 'yes'
* ```
*
* @param fn A single argument function that returns a boolean value
* @returns A function which when called takes the single argument for the function and then returns the truthy or falsy value as needed
*/
export const ifFn = <Argument>(fn: (argument: Argument) => boolean) => {
return <TruthyResult, FalsyResult>(
argument: Argument,
truthy: TruthyResult,
falsy: FalsyResult
) => {
return fn(argument) ? truthy : falsy
}
}
80 changes: 80 additions & 0 deletions src/functions/package.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/* eslint @typescript-eslint/no-shadow:off */
import path from 'path'

import {
getPackage,
hasDependency,
hasDevDependency,
hasPeerDependency,
hasAnyDependency,
hasScript
} from '../index'

describe('Package Fns', () => {
it('should get the package', async () => {
const {
pkg,
pkgPath,
hasDependency,
hasDevDependency,
hasPeerDependency,
hasAnyDependency,
ifDependency,
ifDevDependency,
ifPeerDependency,
ifAnyDependency,
hasScript,
ifScript
} = await getPackage()

expect(pkg.name).toBe('@arcath/utils')
expect(pkgPath).toBe(path.join(process.cwd(), 'package.json'))

await expect(getPackage({cwd: '/fake/does/not/exist'})).rejects.toThrow(
'Could not find package.json'
)

expect(hasDependency('read-pkg-up')).toBeTruthy()
expect(hasDependency('electron')).toBeFalsy()
expect(hasDevDependency('jest')).toBeTruthy()
expect(hasPeerDependency('esbuild')).toBeFalsy()
expect(hasAnyDependency('jest')).toBeTruthy()
expect(ifDependency('read-pkg-up', 'pass', 'fail')).toBe('pass')
expect(ifDevDependency('read-pkg-up', 'pass', 'fail')).toBe('fail')
expect(ifPeerDependency('read-pkg-up', 'pass', 'fail')).toBe('fail')
expect(ifAnyDependency('read-pkg-up', 'pass', 'fail')).toBe('pass')

expect(hasScript('test')).toBeTruthy()
expect(hasScript('upload')).toBeFalsy()
expect(ifScript('test', 'pass', 'fail')).toBe('pass')
})

it('should find dependencies', () => {
const pkg = {
name: 'sample',
version: '1.2.3',
readme: '',
_id: '1',
devDependencies: {jest: '1.2.3'}
}

expect(hasDependency(pkg, 'jest')).toBeFalsy()
expect(hasDevDependency(pkg, 'jest')).toBeTruthy()
expect(hasPeerDependency(pkg, 'jest')).toBeFalsy()
expect(hasAnyDependency(pkg, 'jest')).toBeTruthy()
})

it('should find scripts', () => {
const pkg = {
name: 'sample',
version: '1.2.3',
readme: '',
_id: '1',
devDependencies: {jest: '1.2.3'}
}

expect(hasScript(pkg, 'missing')).toBeFalsy()

expect(hasScript({...pkg, scripts: {run: 'launch'}}, 'run')).toBeTruthy()
})
})
123 changes: 123 additions & 0 deletions src/functions/package.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
import readPkg from 'read-pkg-up'

import {defaults} from './defaults'
import {ifFn} from './if-fn'
import {keys} from './keys'

export interface PackageOptions {
cwd: string
}

/**
* Does the given dependency exist in package.json
*/
export type HasDependency = (dep: string) => boolean

export type IfDependency = <Truthy, Falsy>(
dep: string,
truthy: Truthy,
falsy: Falsy
) => Falsy | Truthy

export interface Package {
pkg: readPkg.NormalizedPackageJson
pkgPath: string
hasDependency: HasDependency
hasDevDependency: HasDependency
hasPeerDependency: HasDependency
hasAnyDependency: HasDependency
hasScript: (script: string) => boolean
ifDependency: IfDependency
ifDevDependency: IfDependency
ifPeerDependency: IfDependency
ifAnyDependency: IfDependency
ifScript: <Truthy, Falsy>(
script: string,
truthy: Truthy,
falsy: Falsy
) => Falsy | Truthy
}

const dependencyFunction = (
key: 'dependencies' | 'devDependencies' | 'peerDependencies'
) => {
return (pkg: readPkg.NormalizedPackageJson, dep: string) => {
if (!pkg[key]) {
return false
}

//eslint-disable-next-line
return keys(pkg[key]!).some(d => d === dep)
}
}

export const hasDependency = dependencyFunction('dependencies')
export const hasDevDependency = dependencyFunction('devDependencies')
export const hasPeerDependency = dependencyFunction('peerDependencies')

export const hasAnyDependency = (
pkg: readPkg.NormalizedPackageJson,
dep: string
) => {
return [
hasDependency(pkg, dep),
hasDevDependency(pkg, dep),
hasPeerDependency(pkg, dep)
].some(r => r)
}

export const hasScript = (
pkg: readPkg.NormalizedPackageJson,
script: string
) => {
if (!pkg.scripts) {
return false
}

return keys(pkg.scripts).includes(script)
}

/**
* Get the current package.json and provide some helpers for interacting with it.
*
* @param options An instance of `PackageOptions` (Optional)
* @returns
*/
export const getPackage = async (
options?: Partial<PackageOptions>
): Promise<Package> => {
const {cwd} = defaults(options, {
cwd: process.cwd()
})

const result = await readPkg({cwd})

if (typeof result === 'undefined') {
throw new Error('Could not find package.json')
}

const {packageJson: pkg, path: pkgPath} = result

return {
pkg,
pkgPath,
hasDependency: (dep: string) => hasDependency(pkg, dep),
hasDevDependency: (dep: string) => hasDevDependency(pkg, dep),
hasPeerDependency: (dep: string) => hasPeerDependency(pkg, dep),
hasAnyDependency: (dep: string) => hasAnyDependency(pkg, dep),
hasScript: (script: string) => hasScript(pkg, script),
ifDependency: ifFn((dep: string) =>
hasDependency(pkg, dep)
) as IfDependency,
ifDevDependency: ifFn((dep: string) =>
hasDevDependency(pkg, dep)
) as IfDependency,
ifPeerDependency: ifFn((dep: string) =>
hasPeerDependency(pkg, dep)
) as IfDependency,
ifAnyDependency: ifFn((dep: string) =>
hasAnyDependency(pkg, dep)
) as IfDependency,
ifScript: ifFn((script: string) => hasScript(pkg, script))
}
}
9 changes: 9 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export {defaults} from './functions/defaults'
export {diffArray} from './functions/diff-array'
export {diffObject} from './functions/diff-object'
export {groupedBy, GroupedArray} from './functions/grouped-by'
export {ifFn} from './functions/if-fn'
export {indexedBy, IndexedArray, IndexedByOptions} from './functions/indexed-by'
export {keys} from './functions/keys'
export {mapProperty} from './functions/map-property'
Expand All @@ -37,6 +38,14 @@ export {reduceTruthy, reduceFalsy} from './functions/reduce'
export {replaceProperty} from './functions/replace-property'
export {propIs, propIsNot} from './functions/selectors'
export {nl2br} from './functions/nl2br'
export {
getPackage,
hasDependency,
hasDevDependency,
hasPeerDependency,
hasAnyDependency,
hasScript
} from './functions/package'
export {parameterize} from './functions/parameterize'
export {pick, omit} from './functions/pick'
export {
Expand Down

0 comments on commit de48040

Please sign in to comment.