Skip to content

Commit

Permalink
feat: syncing multiple files based on workspaces/packages field (#11)
Browse files Browse the repository at this point in the history
  • Loading branch information
jeffijoe committed Oct 7, 2018
1 parent bef3793 commit b003146
Show file tree
Hide file tree
Showing 10 changed files with 333 additions and 67 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
"axios": "^0.18.0",
"chalk": "^2.4.1",
"detect-indent": "^5.0.0",
"glob": "^7.1.3",
"ora": "^3.0.0",
"tslib": "^1.9.3"
},
Expand Down
7 changes: 7 additions & 0 deletions src/__tests__/globber.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { createGlobber } from '../globber'

test('returns the current directory as a match', async () => {
const result = await createGlobber().globPackageFiles(process.cwd())
expect(result).toHaveLength(1)
expect(result[0]).toBe(process.cwd() + '/package.json')
})
76 changes: 69 additions & 7 deletions src/__tests__/type-syncer.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
IPackageFile
} from '../types'
import { createTypeSyncer } from '../type-syncer'
import { IGlobber } from '../globber'

const typedefs: ITypeDefinition[] = [
{
Expand Down Expand Up @@ -35,7 +36,7 @@ const typedefs: ITypeDefinition[] = [
]

function buildSyncer() {
const packageFile: IPackageFile = {
const rootPackageFile: IPackageFile = {
name: 'consumer',
dependencies: {
package1: '^1.0.0',
Expand All @@ -53,6 +54,22 @@ function buildSyncer() {
'@myorg/package7': '^1.0.0',
package8: '~1.0.0',
package9: '1.0.0'
},
packages: ['packages/*'],
workspaces: ['packages/*']
}

const package1File: IPackageFile = {
name: 'package-1',
dependencies: {
package1: '^1.0.0'
}
}

const package2File: IPackageFile = {
name: 'package-1',
dependencies: {
package3: '^1.0.0'
}
}

Expand All @@ -61,24 +78,50 @@ function buildSyncer() {
getLatestTypingsVersion: jest.fn(() => Promise.resolve('1.0.0'))
}
const packageService: IPackageJSONService = {
readPackageFile: jest.fn(() => Promise.resolve(packageFile)),
readPackageFile: jest.fn(async (filepath: string) => {
switch (filepath) {
case 'package.json':
return rootPackageFile
case 'packages/package-1/package.json':
return package1File
case 'packages/package-2/package.json':
return package2File
default:
throw new Error('What?!')
}
}),
writePackageFile: jest.fn(() => Promise.resolve())
}

const globber: IGlobber = {
globPackageFiles: jest.fn(async pattern => {
switch (pattern) {
case 'packages/*':
return [
'packages/package-1/package.json',
'packages/package-2/package.json'
]
default:
return []
}
})
}

return {
typedefSource,
packageService,
packageFile,
syncer: createTypeSyncer(packageService, typedefSource)
rootPackageFile,
syncer: createTypeSyncer(packageService, typedefSource, globber)
}
}

describe('type syncer', () => {
it('adds new packages to the package.json', async () => {
const { syncer, packageService } = buildSyncer()
const result = await syncer.sync('package.json')
const writtenPackage = (packageService.writePackageFile as jest.Mock<any>)
.mock.calls[0][1] as IPackageFile
const writtenPackage = (packageService.writePackageFile as jest.Mock<
any
>).mock.calls.find(c => c[0] === 'package.json')![1] as IPackageFile
expect(writtenPackage.devDependencies).toEqual({
'@types/package1': '^1.0.0',
'@types/package3': '^1.0.0',
Expand All @@ -90,14 +133,33 @@ describe('type syncer', () => {
package4: '^1.0.0',
package5: '^1.0.0'
})
expect(result.newTypings.map(x => x.typingsName).sort()).toEqual([
expect(result.syncedFiles).toHaveLength(3)

expect(result.syncedFiles[0].filePath).toEqual('package.json')
expect(
result.syncedFiles[0].newTypings.map(x => x.typingsName).sort()
).toEqual([
'myorg__package7',
'package1',
'package3',
'package5',
'package8',
'package9'
])

expect(result.syncedFiles[1].filePath).toEqual(
'packages/package-1/package.json'
)
expect(
result.syncedFiles[1].newTypings.map(x => x.typingsName).sort()
).toEqual(['package1'])

expect(result.syncedFiles[2].filePath).toEqual(
'packages/package-2/package.json'
)
expect(
result.syncedFiles[2].newTypings.map(x => x.typingsName).sort()
).toEqual(['package3'])
})

it('does not write packages if options.dry is specified', async () => {
Expand Down
36 changes: 35 additions & 1 deletion src/__tests__/util.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
import { uniq, filterMap, mergeObjects, orderObject, promisify } from '../util'
import {
uniq,
filterMap,
mergeObjects,
orderObject,
promisify,
memoizeAsync
} from '../util'

describe('util', () => {
describe('uniq', () => {
Expand Down Expand Up @@ -66,4 +73,31 @@ describe('util', () => {
expect(err.message).toBe('oh shit')
})
})

describe('memoizeAsync', () => {
it('memoizes promises', async () => {
let i = 0

const m = memoizeAsync((k: string) =>
Promise.resolve(k + (++i).toString())
)
expect([await m('hello'), await m('hello')]).toEqual(['hello1', 'hello1'])
expect([await m('goodbye'), await m('goodbye')]).toEqual([
'goodbye2',
'goodbye2'
])
})

it('removes entry on fail', async () => {
let i = 0

const m = memoizeAsync((k: string) =>
Promise.reject(new Error(k + (++i).toString()))
)
expect([
await m('hello').catch(err => err.message),
await m('hello').catch(err => err.message)
]).toEqual(['hello1', 'hello2'])
})
})
})
11 changes: 7 additions & 4 deletions src/cli.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { createContainer, InjectionMode, asFunction } from 'awilix'
import { createContainer, InjectionMode, asFunction, asValue } from 'awilix'
import { createTypeSyncer } from './type-syncer'
import { ITypeSyncer, ITypeDefinition } from './types'
import chalk from 'chalk'
import * as C from './cli-util'
import glob from 'glob'
import { createTypeDefinitionSource } from './type-definition-source'
import { createPackageJSONFileService } from './package-json-file-service'
import { createGlobber } from './globber';

/**
* Starts the TypeSync CLI.
Expand All @@ -15,9 +17,10 @@ export async function startCli() {
const container = createContainer({
injectionMode: InjectionMode.CLASSIC
}).register({
typeDefinitionSource: asFunction(createTypeDefinitionSource),
packageJSONService: asFunction(createPackageJSONFileService),
typeSyncer: asFunction(createTypeSyncer)
typeDefinitionSource: asFunction(createTypeDefinitionSource).singleton(),
packageJSONService: asFunction(createPackageJSONFileService).singleton(),
globber: asFunction(createGlobber).singleton(),
typeSyncer: asFunction(createTypeSyncer),
})
await _runCli(container.resolve<ITypeSyncer>('typeSyncer'))
} catch (err) {
Expand Down
31 changes: 31 additions & 0 deletions src/globber.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import glob from 'glob'
import * as path from 'path'
import { uniq } from './util'

/**
* Globber interface.
*/
export interface IGlobber {
/**
* Globs for package.json files.
*
* @param pattern
*/
globPackageFiles(pattern: string): Promise<Array<string>>
}

/**
* Creates a globber.
*/
export function createGlobber() {
return {
globPackageFiles(pattern: string) {
return new Promise<Array<string>>((resolve, reject) =>
glob(
path.join(pattern, 'package.json'),
(err, matches) => (err ? reject(err) : resolve(uniq(matches)))
)
)
}
}
}
Loading

0 comments on commit b003146

Please sign in to comment.