Skip to content

Commit

Permalink
feat: handle multiple targets in api-file (#475)
Browse files Browse the repository at this point in the history
  • Loading branch information
oljekechoro authored Sep 13, 2023
1 parent 93c1cfd commit be62a84
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 5 deletions.
25 changes: 25 additions & 0 deletions packages/uniconfig-plugin-api-file/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,29 @@ const config = uniconfig({
})

config.get('someParam') // "bar"

const missingTarget = './foo-missing.json' // this file does not exist
const target2 = './foo2.json'
/** foo2.json content:
{
"foo2": "bar2"
}
*/

const config = uniconfig({
data: {
someParam: '$fromFile:foo'
},
source: {
fromFile: {
data: [missingTarget, target2, target], // in this mode the content of the first existing file is returned
pipeline: 'file>json'
}
}
}, {
mode: 'sync',
pipeline: 'datatree'
})

config.get('someParam') // "bar2"
```
26 changes: 23 additions & 3 deletions packages/uniconfig-plugin-api-file/src/main/ts/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,31 @@ export const name = 'file'

export const pipe: INamedPipe = {
name,
handleSync(_context: IContext, target: string, opts?: IFsOpts): IAny {
handleSync(_context: IContext, target: string | string[], opts?: IFsOpts): IAny {
if (Array.isArray(target)) {
for (const path of target) {
try {
return require('fs').readFileSync(path, processOpts(opts))
}
catch { /* noop */ }
}
throw new Error(`All targets are unreachable (${target})`)
}
return require('fs').readFileSync(target, processOpts(opts))
},
handle(_context: IContext, target: string, opts?: IFsOpts): Promise<IAny> {
return new Promise((resolve: IResolve, reject: IReject): void => {
handle(_context: IContext, target: string | string[], opts?: IFsOpts): Promise<IAny> {
return new Promise(async(resolve: IResolve, reject: IReject) => {
if (Array.isArray(target)) {
for (const path of target) {
try {
resolve(await require('fs/promises').readFile(path, processOpts(opts)))
return
}
catch (e) { /* noop */ }
}
reject(new Error(`All targets are unreachable (${target})`))
return
}
require('fs').readFile(target, processOpts(opts), (err: IAny | null, data: IAny) => {
if (err) {
reject(err)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"foo":"barbaz"}
32 changes: 30 additions & 2 deletions packages/uniconfig-plugin-api-file/src/test/ts/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,48 @@ describe('uniconfig-plugin-api-file', () => {
afterAll(() => context.pipe.flush())

const target = path.resolve(__dirname, './foobar.json')
const target2 = path.resolve(__dirname, './foobarbaz.json')
const missingTarget = path.resolve(__dirname, './foobar-missing.json')
const targetContent = JSON.stringify({foo: 'bar'})
const target2Content = JSON.stringify({foo: 'barbaz'})
const missingTargets = [missingTarget, path.resolve(__dirname, './foobar-missing2.json'), path.resolve(__dirname, './foobar-missing2.json')]

describe('#readSync', () => {
it('gets file data as string', () => {
expect(filePipe.handleSync(context, target)).toEqual(JSON.stringify({foo: 'bar'}))
expect(filePipe.handleSync(context, target)).toEqual(targetContent)
})

it('gets err as result', () => {
expect(() => filePipe.handleSync(context, 'bazqux')).toThrow('ENOENT: no such file or directory, open \'bazqux\'')
})

it('gets content of the first accessible file', () => {
expect(filePipe.handleSync(context, [missingTarget, target, target2]).trim()).toEqual(targetContent)
expect(filePipe.handleSync(context, [target2, missingTarget, target]).trim()).toEqual(target2Content)
})

it('throws an error when all targets are unreachabler', () => {
expect(() => filePipe.handleSync(context, missingTargets)).toThrow(/^All targets are unreachable/)
})
})

describe('#read', () => {
it('resolves promise with string', () => {
return expect(filePipe.handle(context, target)).resolves.toEqual(JSON.stringify({foo: 'bar'}))
return expect(filePipe.handle(context, target)).resolves.toEqual(targetContent)
})

it('gets content of the first accessible file', async() => {
await expect(filePipe.handle(context, [missingTarget, target, target2]).then(d => d.trim())).resolves.toEqual(targetContent)
await expect(filePipe.handle(context, [target2, missingTarget, target]).then(d => d.trim())).resolves.toEqual(target2Content)
})

it('throws an error when all targets are unreachable', async() => {
await expect(
filePipe.handle(
context,
missingTargets,
),
).rejects.toMatchObject({message: /^All targets are unreachable/})
})

it('rejects promise with err', () => {
Expand Down

0 comments on commit be62a84

Please sign in to comment.