@@ -4,18 +4,20 @@ import { conat } from "@cocalc/conat/client";
44export interface Filesystem {
55 appendFile : ( path : string , data : string | Buffer , encoding ?) => Promise < void > ;
66 chmod : ( path : string , mode : string | number ) => Promise < void > ;
7+ constants : ( ) => Promise < { [ key : string ] : number } > ;
78 copyFile : ( src : string , dest : string ) => Promise < void > ;
89 cp : ( src : string , dest : string , options ?) => Promise < void > ;
910 exists : ( path : string ) => Promise < void > ;
1011 link : ( existingPath : string , newPath : string ) => Promise < void > ;
12+ lstat : ( path : string ) => Promise < IStats > ;
1113 mkdir : ( path : string , options ?) => Promise < void > ;
1214 readFile : ( path : string , encoding ?: any ) => Promise < string | Buffer > ;
1315 readdir : ( path : string ) => Promise < string [ ] > ;
1416 realpath : ( path : string ) => Promise < string > ;
1517 rename : ( oldPath : string , newPath : string ) => Promise < void > ;
1618 rm : ( path : string , options ?) => Promise < void > ;
1719 rmdir : ( path : string , options ?) => Promise < void > ;
18- stat : ( path : string ) => Promise < Stats > ;
20+ stat : ( path : string ) => Promise < IStats > ;
1921 symlink : ( target : string , path : string ) => Promise < void > ;
2022 truncate : ( path : string , len ?: number ) => Promise < void > ;
2123 unlink : ( path : string ) => Promise < void > ;
@@ -27,7 +29,7 @@ export interface Filesystem {
2729 writeFile : ( path : string , data : string | Buffer ) => Promise < void > ;
2830}
2931
30- export interface Stats {
32+ interface IStats {
3133 dev : number ;
3234 ino : number ;
3335 mode : number ;
@@ -48,6 +50,48 @@ export interface Stats {
4850 birthtime : Date ;
4951}
5052
53+ class Stats {
54+ dev : number ;
55+ ino : number ;
56+ mode : number ;
57+ nlink : number ;
58+ uid : number ;
59+ gid : number ;
60+ rdev : number ;
61+ size : number ;
62+ blksize : number ;
63+ blocks : number ;
64+ atimeMs : number ;
65+ mtimeMs : number ;
66+ ctimeMs : number ;
67+ birthtimeMs : number ;
68+ atime : Date ;
69+ mtime : Date ;
70+ ctime : Date ;
71+ birthtime : Date ;
72+
73+ constructor ( private constants : { [ key : string ] : number } ) { }
74+
75+ isSymbolicLink = ( ) =>
76+ ( this . mode & this . constants . S_IFMT ) === this . constants . S_IFLNK ;
77+
78+ isFile = ( ) => ( this . mode & this . constants . S_IFMT ) === this . constants . S_IFREG ;
79+
80+ isDirectory = ( ) =>
81+ ( this . mode & this . constants . S_IFMT ) === this . constants . S_IFDIR ;
82+
83+ isBlockDevice = ( ) =>
84+ ( this . mode & this . constants . S_IFMT ) === this . constants . S_IFBLK ;
85+
86+ isCharacterDevice = ( ) =>
87+ ( this . mode & this . constants . S_IFMT ) === this . constants . S_IFCHR ;
88+
89+ isFIFO = ( ) => ( this . mode & this . constants . S_IFMT ) === this . constants . S_IFIFO ;
90+
91+ isSocket = ( ) =>
92+ ( this . mode & this . constants . S_IFMT ) === this . constants . S_IFSOCK ;
93+ }
94+
5195interface Options {
5296 service : string ;
5397 client ?: Client ;
@@ -64,18 +108,24 @@ export async function fsServer({ service, fs, client }: Options) {
64108 async chmod ( path : string , mode : string | number ) {
65109 await ( await fs ( this . subject ) ) . chmod ( path , mode ) ;
66110 } ,
111+ async constants ( ) : Promise < { [ key : string ] : number } > {
112+ return await ( await fs ( this . subject ) ) . constants ( ) ;
113+ } ,
67114 async copyFile ( src : string , dest : string ) {
68115 await ( await fs ( this . subject ) ) . copyFile ( src , dest ) ;
69116 } ,
70117 async cp ( src : string , dest : string , options ?) {
71118 await ( await fs ( this . subject ) ) . cp ( src , dest , options ) ;
72119 } ,
73120 async exists ( path : string ) {
74- await ( await fs ( this . subject ) ) . exists ( path ) ;
121+ return await ( await fs ( this . subject ) ) . exists ( path ) ;
75122 } ,
76123 async link ( existingPath : string , newPath : string ) {
77124 await ( await fs ( this . subject ) ) . link ( existingPath , newPath ) ;
78125 } ,
126+ async lstat ( path : string ) : Promise < IStats > {
127+ return await ( await fs ( this . subject ) ) . lstat ( path ) ;
128+ } ,
79129 async mkdir ( path : string , options ?) {
80130 await ( await fs ( this . subject ) ) . mkdir ( path , options ) ;
81131 } ,
@@ -89,35 +139,35 @@ export async function fsServer({ service, fs, client }: Options) {
89139 return await ( await fs ( this . subject ) ) . realpath ( path ) ;
90140 } ,
91141 async rename ( oldPath : string , newPath : string ) {
92- return await ( await fs ( this . subject ) ) . rename ( oldPath , newPath ) ;
142+ await ( await fs ( this . subject ) ) . rename ( oldPath , newPath ) ;
93143 } ,
94144 async rm ( path : string , options ?) {
95- return await ( await fs ( this . subject ) ) . rm ( path , options ) ;
145+ await ( await fs ( this . subject ) ) . rm ( path , options ) ;
96146 } ,
97147 async rmdir ( path : string , options ?) {
98- return await ( await fs ( this . subject ) ) . rmdir ( path , options ) ;
148+ await ( await fs ( this . subject ) ) . rmdir ( path , options ) ;
99149 } ,
100- async stat ( path : string ) : Promise < Stats > {
150+ async stat ( path : string ) : Promise < IStats > {
101151 return await ( await fs ( this . subject ) ) . stat ( path ) ;
102152 } ,
103153 async symlink ( target : string , path : string ) {
104- return await ( await fs ( this . subject ) ) . symlink ( target , path ) ;
154+ await ( await fs ( this . subject ) ) . symlink ( target , path ) ;
105155 } ,
106156 async truncate ( path : string , len ?: number ) {
107- return await ( await fs ( this . subject ) ) . truncate ( path , len ) ;
157+ await ( await fs ( this . subject ) ) . truncate ( path , len ) ;
108158 } ,
109159 async unlink ( path : string ) {
110- return await ( await fs ( this . subject ) ) . unlink ( path ) ;
160+ await ( await fs ( this . subject ) ) . unlink ( path ) ;
111161 } ,
112162 async utimes (
113163 path : string ,
114164 atime : number | string | Date ,
115165 mtime : number | string | Date ,
116166 ) {
117- return await ( await fs ( this . subject ) ) . utimes ( path , atime , mtime ) ;
167+ await ( await fs ( this . subject ) ) . utimes ( path , atime , mtime ) ;
118168 } ,
119169 async writeFile ( path : string , data : string | Buffer ) {
120- return await ( await fs ( this . subject ) ) . writeFile ( path , data ) ;
170+ await ( await fs ( this . subject ) ) . writeFile ( path , data ) ;
121171 } ,
122172 } ,
123173 ) ;
@@ -130,5 +180,30 @@ export function fsClient({
130180 client ?: Client ;
131181 subject : string ;
132182} ) {
133- return ( client ?? conat ( ) ) . call < Filesystem > ( subject ) ;
183+ let call = ( client ?? conat ( ) ) . call < Filesystem > ( subject ) ;
184+
185+ let constants : any = null ;
186+ const stat0 = call . stat . bind ( call ) ;
187+ call . stat = async ( path : string ) => {
188+ const s = await stat0 ( path ) ;
189+ constants = constants ?? ( await call . constants ( ) ) ;
190+ const stats = new Stats ( constants ) ;
191+ for ( const k in s ) {
192+ stats [ k ] = s [ k ] ;
193+ }
194+ return stats ;
195+ } ;
196+
197+ const lstat0 = call . lstat . bind ( call ) ;
198+ call . lstat = async ( path : string ) => {
199+ const s = await lstat0 ( path ) ;
200+ constants = constants ?? ( await call . constants ( ) ) ;
201+ const stats = new Stats ( constants ) ;
202+ for ( const k in s ) {
203+ stats [ k ] = s [ k ] ;
204+ }
205+ return stats ;
206+ } ;
207+
208+ return call ;
134209}
0 commit comments