-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathio_bun.mjs
More file actions
186 lines (154 loc) · 5.59 KB
/
Copy pathio_bun.mjs
File metadata and controls
186 lines (154 loc) · 5.59 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
/*
Compare `./io_deno.mjs`. The two modules should have the same interface.
For consumer code, the pseudo-module `./io` should automatically resolve
to the engine-specific implementation via `package.json`.`exports`.
*/
// deno-lint-ignore-file no-process-global
/* global Bun, process */
import * as fs from 'node:fs'
import * as fsp from 'node:fs/promises'
import * as os from 'node:os'
import * as l from './lang.mjs'
import * as pt from './path.mjs'
export const ENV = process.env
export function cwd() {return process.cwd()}
export function exit(...src) {return process.exit(...src)}
export function isErrNotFound(val) {return val?.code === `ENOENT`}
export function skipErrNotFound(val) {return l.errSkip(val, isErrNotFound)}
export function validPath(val) {
if (l.isKey(val)) return val
if (l.isInst(val, URL)) return val
return l.reqScalar(val).toString()
}
export function validPathOpt(val) {return l.opt(val, validPath)}
export function readFileText(path) {return Bun.file(validPath(path)).text()}
export function readFileTextSync(path) {
return fs.readFileSync(validPath(path), {encoding: `utf8`})
}
export function readFileBytes(path) {return Bun.file(validPath(path)).bytes()}
export function readFileBytesSync(path) {return fs.readFileSync(validPath(path))}
export function readFileTextOpt(path) {
if (l.isNil(path)) return undefined
return readFileText(path).catch(skipErrNotFound)
}
export function readFileTextOptSync(path) {
if (l.isNil(path)) return undefined
try {return readFileTextSync(path)}
catch (err) {
if (isErrNotFound(err)) return undefined
throw err
}
}
export function writeFile(path, body) {
path = validPath(path)
if (l.isNil(body)) return Bun.write(path, ``)
if (l.isStr(body)) return Bun.write(path, body)
if (l.isInst(body, Uint8Array)) return Bun.write(path, body)
if (l.isInst(body, Response)) return Bun.write(path, body)
if (l.isInst(body, ReadableStream)) return Bun.write(path, new Response(body))
throw TypeError(`unable to write ${l.show(path)}: file body must be [string | Uint8Array | ReadableStream | Response], got ${l.show(body)}`)
}
export function writeFileSync(path, body, opt) {
path = validPath(path)
l.optRec(opt)
if (l.isNil(body)) return fs.truncateSync(path)
if (l.isStr(body)) return fs.writeFileSync(path, body, opt)
if (l.isInst(body, Uint8Array)) return fs.writeFileSync(path, body, opt)
throw TypeError(`unable to write ${l.show(path)}: file body must be [string | Uint8Array], got ${l.show(body)}`)
}
// Directory removal is assumed to be always recursive.
export function remove(path, opt) {
path = validPath(path)
l.optRec(opt)
if (opt?.recursive) return fsp.rmdir(path, opt)
return fsp.unlink(validPath(path), opt)
}
// Directory removal is assumed to be always recursive.
export function removeSync(path, opt) {
path = validPath(path)
l.optRec(opt)
if (opt?.recursive) return fs.rmdirSync(path, opt)
return fs.unlinkSync(validPath(path))
}
export function exists(path) {return fs.exists(validPath(path))}
export function existsSync(path) {return fs.existsSync(validPath(path))}
export async function stat(path) {
return statNorm(await Bun.file(validPath(path)).stat())
}
export function statSync(path) {
return statNorm(fs.statSync(validPath(path)))
}
export function statOpt(path) {
path = validPath(path)
if (l.isNil(path) || path === ``) return undefined
return stat(path).catch(skipErrNotFound)
}
export function statOptSync(path) {
path = validPath(path)
if (l.isNil(path) || path === ``) return undefined
try {return statSync(path)}
catch (err) {
if (isErrNotFound(err)) return undefined
throw err
}
}
export function statNorm(src) {
if (!l.optRec(src)) return undefined
return {
__proto__: null,
isDir: src.isDirectory(),
isFile: src.isFile(),
isSymlink: src.isSymbolicLink(),
isBlockDevice: src.isBlockDevice(),
isCharDevice: src.isCharacterDevice(),
isSocket: src.isSocket(),
isFifo: src.isFIFO(),
size: src.size,
mtime: src.mtimeMs,
atime: src.atimeMs,
birthtime: src.birthtimeMs,
ctime: src.ctimeMs,
uid: src.uid,
gid: src.gid,
dev: src.dev,
ino: src.ino,
rdev: src.rdev,
mode: src.mode,
nlink: src.nlink,
blksize: src.blksize,
blocks: src.blocks,
}
}
// Caller must eventually call `.cancel` on the stream.
export function fileReadStream(path) {
return Bun.file(validPath(path)).stream()
}
export function mkdir(path, opt) {return fsp.mkdir(validPath(path), opt)}
export function mkdirSync(path, opt) {return fs.mkdirSync(validPath(path), opt)}
export function mkdirTemp(opt) {return fsp.mkdtemp(tmpOpt(opt))}
export function mkdirTempSync(opt) {return fs.mkdtempSync(tmpOpt(opt))}
// Aims to align with Deno's default behavior.
function tmpOpt(opt) {
l.optRec(opt)
const dir = validPathOpt(opt?.dir) ?? os.tmpdir()
const pre = l.optStr(opt?.prefix)
return pre ? pt.join(dir, pre) : pt.dirLike(dir)
}
export function readDir(path, opt) {return fsp.readdir(validPath(path), opt)}
export function readDirSync(path, opt) {return fs.readdirSync(validPath(path), opt)}
export function rename(prev, next) {
return fsp.rename(validPath(prev), validPath(next))
}
export function renameSync(prev, next) {
return fs.renameSync(validPath(prev), validPath(next))
}
// Defined for symmetry with `io_deno.mjs`.
export function watchCwd() {return watchRel(`.`)}
// Defined for symmetry with `io_deno.mjs`.
export async function* watchRel(base) {
base = l.reqStr(validPath(base))
const iter = fsp.watch(base, {recursive: true})
for await (const {eventType: type, filename: path} of iter) {
yield {type, path}
}
}