@@ -4,18 +4,20 @@ import { conat } from "@cocalc/conat/client";
4
4
export interface Filesystem {
5
5
appendFile : ( path : string , data : string | Buffer , encoding ?) => Promise < void > ;
6
6
chmod : ( path : string , mode : string | number ) => Promise < void > ;
7
+ constants : ( ) => Promise < { [ key : string ] : number } > ;
7
8
copyFile : ( src : string , dest : string ) => Promise < void > ;
8
9
cp : ( src : string , dest : string , options ?) => Promise < void > ;
9
10
exists : ( path : string ) => Promise < void > ;
10
11
link : ( existingPath : string , newPath : string ) => Promise < void > ;
12
+ lstat : ( path : string ) => Promise < IStats > ;
11
13
mkdir : ( path : string , options ?) => Promise < void > ;
12
14
readFile : ( path : string , encoding ?: any ) => Promise < string | Buffer > ;
13
15
readdir : ( path : string ) => Promise < string [ ] > ;
14
16
realpath : ( path : string ) => Promise < string > ;
15
17
rename : ( oldPath : string , newPath : string ) => Promise < void > ;
16
18
rm : ( path : string , options ?) => Promise < void > ;
17
19
rmdir : ( path : string , options ?) => Promise < void > ;
18
- stat : ( path : string ) => Promise < Stats > ;
20
+ stat : ( path : string ) => Promise < IStats > ;
19
21
symlink : ( target : string , path : string ) => Promise < void > ;
20
22
truncate : ( path : string , len ?: number ) => Promise < void > ;
21
23
unlink : ( path : string ) => Promise < void > ;
@@ -27,7 +29,7 @@ export interface Filesystem {
27
29
writeFile : ( path : string , data : string | Buffer ) => Promise < void > ;
28
30
}
29
31
30
- export interface Stats {
32
+ interface IStats {
31
33
dev : number ;
32
34
ino : number ;
33
35
mode : number ;
@@ -48,6 +50,48 @@ export interface Stats {
48
50
birthtime : Date ;
49
51
}
50
52
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
+
51
95
interface Options {
52
96
service : string ;
53
97
client ?: Client ;
@@ -64,18 +108,24 @@ export async function fsServer({ service, fs, client }: Options) {
64
108
async chmod ( path : string , mode : string | number ) {
65
109
await ( await fs ( this . subject ) ) . chmod ( path , mode ) ;
66
110
} ,
111
+ async constants ( ) : Promise < { [ key : string ] : number } > {
112
+ return await ( await fs ( this . subject ) ) . constants ( ) ;
113
+ } ,
67
114
async copyFile ( src : string , dest : string ) {
68
115
await ( await fs ( this . subject ) ) . copyFile ( src , dest ) ;
69
116
} ,
70
117
async cp ( src : string , dest : string , options ?) {
71
118
await ( await fs ( this . subject ) ) . cp ( src , dest , options ) ;
72
119
} ,
73
120
async exists ( path : string ) {
74
- await ( await fs ( this . subject ) ) . exists ( path ) ;
121
+ return await ( await fs ( this . subject ) ) . exists ( path ) ;
75
122
} ,
76
123
async link ( existingPath : string , newPath : string ) {
77
124
await ( await fs ( this . subject ) ) . link ( existingPath , newPath ) ;
78
125
} ,
126
+ async lstat ( path : string ) : Promise < IStats > {
127
+ return await ( await fs ( this . subject ) ) . lstat ( path ) ;
128
+ } ,
79
129
async mkdir ( path : string , options ?) {
80
130
await ( await fs ( this . subject ) ) . mkdir ( path , options ) ;
81
131
} ,
@@ -89,35 +139,35 @@ export async function fsServer({ service, fs, client }: Options) {
89
139
return await ( await fs ( this . subject ) ) . realpath ( path ) ;
90
140
} ,
91
141
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 ) ;
93
143
} ,
94
144
async rm ( path : string , options ?) {
95
- return await ( await fs ( this . subject ) ) . rm ( path , options ) ;
145
+ await ( await fs ( this . subject ) ) . rm ( path , options ) ;
96
146
} ,
97
147
async rmdir ( path : string , options ?) {
98
- return await ( await fs ( this . subject ) ) . rmdir ( path , options ) ;
148
+ await ( await fs ( this . subject ) ) . rmdir ( path , options ) ;
99
149
} ,
100
- async stat ( path : string ) : Promise < Stats > {
150
+ async stat ( path : string ) : Promise < IStats > {
101
151
return await ( await fs ( this . subject ) ) . stat ( path ) ;
102
152
} ,
103
153
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 ) ;
105
155
} ,
106
156
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 ) ;
108
158
} ,
109
159
async unlink ( path : string ) {
110
- return await ( await fs ( this . subject ) ) . unlink ( path ) ;
160
+ await ( await fs ( this . subject ) ) . unlink ( path ) ;
111
161
} ,
112
162
async utimes (
113
163
path : string ,
114
164
atime : number | string | Date ,
115
165
mtime : number | string | Date ,
116
166
) {
117
- return await ( await fs ( this . subject ) ) . utimes ( path , atime , mtime ) ;
167
+ await ( await fs ( this . subject ) ) . utimes ( path , atime , mtime ) ;
118
168
} ,
119
169
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 ) ;
121
171
} ,
122
172
} ,
123
173
) ;
@@ -130,5 +180,30 @@ export function fsClient({
130
180
client ?: Client ;
131
181
subject : string ;
132
182
} ) {
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 ;
134
209
}
0 commit comments