Skip to content

Commit 686e62b

Browse files
committed
feat: Add access methods that translate errors into issues
1 parent fb6b0a7 commit 686e62b

File tree

3 files changed

+72
-0
lines changed

3 files changed

+72
-0
lines changed

src/files/access.test.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import { assert, assertObjectMatch } from '@std/assert'
2+
import { basename, dirname } from '@std/path'
3+
import { BIDSFileDeno } from './deno.ts'
4+
5+
export function testAsyncFileAccess(
6+
name: string,
7+
fn: (file: BIDSFileDeno, ...args: any[]) => Promise<any>,
8+
...args: any[]
9+
) {
10+
Deno.test(name, async (t) => {
11+
await t.step('Dangling symlink', async () => {
12+
const file = new BIDSFileDeno('tests/data', '/broken-symlink')
13+
try {
14+
await fn(file, ...args)
15+
assert(false, 'Expected error')
16+
} catch (e: any) {
17+
assertObjectMatch(e, {
18+
code: 'FILE_READ',
19+
subCode: 'NotFound',
20+
location: '/broken-symlink',
21+
})
22+
}
23+
})
24+
await t.step('Insufficient permissions', async () => {
25+
const tmpfile = await Deno.makeTempFile()
26+
await Deno.chmod(tmpfile, 0o000)
27+
const file = new BIDSFileDeno('', tmpfile)
28+
try {
29+
await fn(file, ...args)
30+
assert(false, 'Expected error')
31+
} catch (e: any) {
32+
assertObjectMatch(e, { code: 'FILE_READ', subCode: 'PermissionDenied' })
33+
}
34+
})
35+
})
36+
}

src/files/access.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { type BIDSFile } from '../types/filetree.ts'
2+
import { type Issue } from '../types/issues.ts'
3+
4+
function IOErrorToIssue(err: { code: string; name: string }): Issue {
5+
const subcode = err.name
6+
let issueMessage: string | undefined = undefined
7+
if (err.code === 'ENOENT') {
8+
issueMessage = 'Possible dangling symbolic link'
9+
}
10+
return { code: 'FILE_READ', subCode: err.name, issueMessage }
11+
}
12+
13+
export function openStream(file: BIDSFile): ReadableStream<Uint8Array<ArrayBuffer>> {
14+
try {
15+
return file.stream
16+
} catch (err: any) {
17+
throw { location: file.path, ...IOErrorToIssue(err) }
18+
}
19+
}
20+
21+
export async function readBytes(
22+
file: BIDSFile,
23+
size: number,
24+
offset = 0,
25+
): Promise<Uint8Array<ArrayBuffer>> {
26+
return file.readBytes(size, offset).catch((err: any) => {
27+
throw { location: file.path, ...IOErrorToIssue(err) }
28+
})
29+
}
30+
31+
export async function readText(file: BIDSFile): Promise<string> {
32+
return file.text().catch((err: any) => {
33+
throw { location: file.path, ...IOErrorToIssue(err) }
34+
})
35+
}

tests/data/broken-symlink

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
dangling-target

0 commit comments

Comments
 (0)