import { Stats } from 'fs' ; /**
 * Constants (defined in `stat.h`).
 */ const S_IFMT = 61440 ; const S_IFIFO = 4096 ; const S_IFCHR = 8192 ; const S_IFDIR = 16384 ; const S_IFBLK = 24576 ; const S_IFREG = 32768 ; const S_IFLNK = 40960 ; const S_IFSOCK = 49152 ; const S_IFWHT = 57344 ; const S_ISUID = 2048 ; const S_ISGID = 1024 ; const S_ISVTX = 512 ; const S_IRUSR = 256 ; const S_IWUSR = 128 ; const S_IXUSR = 64 ; const S_IRGRP = 32 ; const S_IWGRP = 16 ; const S_IXGRP = 8 ; const S_IROTH = 4 ; const S_IWOTH = 2 ; const S_IXOTH = 1 ; function createMode ( stat ? ) { return new createMode . Mode ( stat ) ; } namespace createMode { export type StatsMode = Pick < Stats , 'mode' > ; export function isStatsMode ( v ) { return v && typeof v . mode === 'number' ; } export class RWX { protected static r : number ; protected static w : number ; protected static x : number ; private stat : StatsMode ; constructor ( stat ) { this . stat = stat ; } public get read ( ) : boolean { return Boolean ( this . stat . mode & ( this . constructor as typeof RWX ) . r ) ; } public set read ( v ) { if ( v ) { this . stat . mode |= ( this . constructor as typeof RWX ) . r ; } else { this . stat . mode &= ~ ( this . constructor as typeof RWX ) . r ; } } public get write ( ) : boolean { return Boolean ( this . stat . mode & ( this . constructor as typeof RWX ) . w ) ; } public set write ( v ) { if ( v ) { this . stat . mode |= ( this . constructor as typeof RWX ) . w ; } else { this . stat . mode &= ~ ( this . constructor as typeof RWX ) . w ; } } public get execute ( ) : boolean { return Boolean ( this . stat . mode & ( this . constructor as typeof RWX ) . x ) ; } public set execute ( v ) { if ( v ) { this . stat . mode |= ( this . constructor as typeof RWX ) . x ; } else { this . stat . mode &= ~ ( this . constructor as typeof RWX ) . x ; } } } export class Owner extends RWX { protected static r = S_IRUSR ; protected static w = S_IWUSR ; protected static x = S_IXUSR ; } export class Group extends RWX { protected static r = S_IRGRP ; protected static w = S_IWGRP ; protected static x = S_IXGRP ; } export class Others extends RWX { protected static r = S_IROTH ; protected static w = S_IWOTH ; protected static x = S_IXOTH ; } export class Mode { public owner : Owner ; public group : Group ; public others : Others ; private stat : StatsMode ; constructor ( stat ? ) { if ( typeof stat === 'number' ) { this . stat = { mode : stat } ; } else if ( isStatsMode ( stat ) ) { this . stat = stat ; } else { this . stat = { mode : 0 } ; } this . owner = new Owner ( this . stat ) ; this . group = new Group ( this . stat ) ; this . others = new Others ( this . stat ) ; } private checkModeProperty ( property , set ? ) { const { mode } = this . stat ; if ( set ) { this . stat . mode = ( ( mode | S_IFMT ) & property ) | ( mode & ~ S_IFMT ) ; } return ( mode & S_IFMT ) === property ; } public isDirectory ( v ? ) { return this . checkModeProperty ( S_IFDIR , v ) ; } public isFile ( v ? ) { return this . checkModeProperty ( S_IFREG , v ) ; } public isBlockDevice ( v ? ) { return this . checkModeProperty ( S_IFBLK , v ) ; } public isCharacterDevice ( v ? ) { return this . checkModeProperty ( S_IFCHR , v ) ; } public isSymbolicLink ( v ? ) { return this . checkModeProperty ( S_IFLNK , v ) ; } public isFIFO ( v ? ) { return this . checkModeProperty ( S_IFIFO , v ) ; } public isSocket ( v ? ) { return this . checkModeProperty ( S_IFSOCK , v ) ; } return { String } api public toOctal ( ) { const octal = this . stat . mode & 4095 ; return `0000${ octal . toString ( 8 ) }` . slice ( - 4 ) ; } return { String } api public toString ( ) { const str = [ ] ; if ( this . isDirectory ( ) ) { str . push ( 'd' ) ; } else if ( this . isFile ( ) ) { str . push ( '-' ) ; } else if ( this . isBlockDevice ( ) ) { str . push ( 'b' ) ; } else if ( this . isCharacterDevice ( ) ) { str . push ( 'c' ) ; } else if ( this . isSymbolicLink ( ) ) { str . push ( 'l' ) ; } else if ( this . isFIFO ( ) ) { str . push ( 'p' ) ; } else if ( this . isSocket ( ) ) { str . push ( 's' ) ; } else { const mode = this . valueOf ( ) ; const err = new TypeError ( `Unexpected "file type": mode=${ mode }` ) ; throw err ; } str . push ( this . owner . read ? 'r' : '-' ) ; str . push ( this . owner . write ? 'w' : '-' ) ; if ( this . setuid ) { str . push ( this . owner . execute ? 's' : 'S' ) ; } else { str . push ( this . owner . execute ? 'x' : '-' ) ; } str . push ( this . group . read ? 'r' : '-' ) ; str . push ( this . group . write ? 'w' : '-' ) ; if ( this . setgid ) { str . push ( this . group . execute ? 's' : 'S' ) ; } else { str . push ( this . group . execute ? 'x' : '-' ) ; } str . push ( this . others . read ? 'r' : '-' ) ; str . push ( this . others . write ? 'w' : '-' ) ; if ( this . sticky ) { str . push ( this . others . execute ? 't' : 'T' ) ; } else { str . push ( this . others . execute ? 'x' : '-' ) ; } return str . join ( '' ) ; } public valueOf ( ) { return this . stat . mode ; } get setuid ( ) : boolean { return Boolean ( this . stat . mode & S_ISUID ) ; } set setuid ( v ) { if ( v ) { this . stat . mode |= S_ISUID ; } else { this . stat . mode &= ~ S_ISUID ; } } get setgid ( ) : boolean { return Boolean ( this . stat . mode & S_ISGID ) ; } set setgid ( v ) { if ( v ) { this . stat . mode |= S_ISGID ; } else { this . stat . mode &= ~ S_ISGID ; } } get sticky ( ) : boolean { return Boolean ( this . stat . mode & S_ISVTX ) ; } set sticky ( v ) { if ( v ) { this . stat . mode |= S_ISVTX ; } else { this . stat . mode &= ~ S_ISVTX ; } } } createMode . prototype = Mode . prototype ; } export = createMode ;