Files
NebulaShell/website/node_modules/touch/index.js
Falck e5d578a849 chore: disable delete confirmation in VS Code explorer
Disable the confirmation dialog when deleting files in the VS Code explorer to streamline the development workflow and reduce friction during file management operations.
2026-04-25 15:56:37 +08:00

225 lines
4.9 KiB
JavaScript

'use strict'
const EE = require('events').EventEmitter
const cons = require('constants')
const fs = require('fs')
module.exports = (f, options, cb) => {
if (typeof options === 'function')
cb = options, options = {}
const p = new Promise((res, rej) => {
new Touch(validOpts(options, f, null))
.on('done', res).on('error', rej)
})
return cb ? p.then(res => cb(null, res), cb) : p
}
module.exports.sync = module.exports.touchSync = (f, options) =>
(new TouchSync(validOpts(options, f, null)), undefined)
module.exports.ftouch = (fd, options, cb) => {
if (typeof options === 'function')
cb = options, options = {}
const p = new Promise((res, rej) => {
new Touch(validOpts(options, null, fd))
.on('done', res).on('error', rej)
})
return cb ? p.then(res => cb(null, res), cb) : p
}
module.exports.ftouchSync = (fd, opt) =>
(new TouchSync(validOpts(opt, null, fd)), undefined)
const validOpts = (options, path, fd) => {
options = Object.create(options || {})
options.fd = fd
options.path = path
// {mtime: true}, {ctime: true}
// If set to something else, then treat as epoch ms value
const now = new Date(options.time || Date.now()).getTime() / 1000
if (!options.atime && !options.mtime)
options.atime = options.mtime = now
else {
if (true === options.atime)
options.atime = now
if (true === options.mtime)
options.mtime = now
}
let oflags = 0
if (!options.force)
oflags = oflags | cons.O_RDWR
if (!options.nocreate)
oflags = oflags | cons.O_CREAT
options.oflags = oflags
return options
}
class Touch extends EE {
constructor (options) {
super(options)
this.fd = options.fd
this.path = options.path
this.atime = options.atime
this.mtime = options.mtime
this.ref = options.ref
this.nocreate = !!options.nocreate
this.force = !!options.force
this.closeAfter = options.closeAfter
this.oflags = options.oflags
this.options = options
if (typeof this.fd !== 'number') {
this.closeAfter = true
this.open()
} else
this.onopen(null, this.fd)
}
emit (ev, data) {
// we only emit when either done or erroring
// in both cases, need to close
this.close()
return super.emit(ev, data)
}
close () {
if (typeof this.fd === 'number' && this.closeAfter)
fs.close(this.fd, () => {})
}
open () {
fs.open(this.path, this.oflags, (er, fd) => this.onopen(er, fd))
}
onopen (er, fd) {
if (er) {
if (er.code === 'EISDIR')
this.onopen(null, null)
else if (er.code === 'ENOENT' && this.nocreate)
this.emit('done')
else
this.emit('error', er)
} else {
this.fd = fd
if (this.ref)
this.statref()
else if (!this.atime || !this.mtime)
this.fstat()
else
this.futimes()
}
}
statref () {
fs.stat(this.ref, (er, st) => {
if (er)
this.emit('error', er)
else
this.onstatref(st)
})
}
onstatref (st) {
this.atime = this.atime && st.atime.getTime()/1000
this.mtime = this.mtime && st.mtime.getTime()/1000
if (!this.atime || !this.mtime)
this.fstat()
else
this.futimes()
}
fstat () {
const stat = this.fd ? 'fstat' : 'stat'
const target = this.fd || this.path
fs[stat](target, (er, st) => {
if (er)
this.emit('error', er)
else
this.onfstat(st)
})
}
onfstat (st) {
if (typeof this.atime !== 'number')
this.atime = st.atime.getTime()/1000
if (typeof this.mtime !== 'number')
this.mtime = st.mtime.getTime()/1000
this.futimes()
}
futimes () {
const utimes = this.fd ? 'futimes' : 'utimes'
const target = this.fd || this.path
fs[utimes](target, ''+this.atime, ''+this.mtime, er => {
if (er)
this.emit('error', er)
else
this.emit('done')
})
}
}
class TouchSync extends Touch {
open () {
try {
this.onopen(null, fs.openSync(this.path, this.oflags))
} catch (er) {
this.onopen(er)
}
}
statref () {
let threw = true
try {
this.onstatref(fs.statSync(this.ref))
threw = false
} finally {
if (threw)
this.close()
}
}
fstat () {
let threw = true
const stat = this.fd ? 'fstatSync' : 'statSync'
const target = this.fd || this.path
try {
this.onfstat(fs[stat](target))
threw = false
} finally {
if (threw)
this.close()
}
}
futimes () {
let threw = true
const utimes = this.fd ? 'futimesSync' : 'utimesSync'
const target = this.fd || this.path
try {
fs[utimes](target, this.atime, this.mtime)
threw = false
} finally {
if (threw)
this.close()
}
this.emit('done')
}
close () {
if (typeof this.fd === 'number' && this.closeAfter)
try { fs.closeSync(this.fd) } catch (er) {}
}
}