@@ -18,33 +18,37 @@ function isRecord(obj: unknown): obj is Record<string, unknown> {
18
18
return obj . constructor === Object ;
19
19
}
20
20
21
+ export type Flag = FlagRead | FlagReadWrite ;
22
+ export type FlagRead = 'r' ;
23
+ export type FlagReadWrite = 'rw' ;
24
+
21
25
export class FileSystemAbstraction implements FileSystem {
22
26
protocol = 'abstract' ;
23
27
/**
24
28
* Is the systems array currently ordered
25
29
* @see FileSystemAbstraction.sortSystems
26
30
*/
27
31
private isOrdered = true ;
28
- systems : { path : string ; system : FileSystem } [ ] = [ ] ;
32
+ systems : { path : string ; system : FileSystem ; flag : Flag } [ ] = [ ] ;
29
33
30
34
/**
31
35
* Register a file system to a specific path which can then be used with any `fsa` command
32
36
*
33
37
* @example
34
- * fsa.register('s3://', fsS3)
35
- * fsa.register('s3://bucket-a/key-a', specificS3)
38
+ * fsa.register('s3://', fsS3, 'rw' )
39
+ * fsa.register('s3://bucket-a/key-a', specificS3, 'r' )
36
40
* fsa.register('http://', fsHttp)
37
41
*
38
42
*/
39
- register ( path : string , system : FileSystem ) : void {
43
+ register ( path : string , system : FileSystem , flag : Flag = 'rw' ) : void {
40
44
for ( let i = 0 ; i < this . systems . length ; i ++ ) {
41
45
const sys = this . systems [ i ] ;
42
- if ( sys . path === path ) {
43
- this . systems . splice ( i , 1 , { path, system } ) ;
46
+ if ( sys . path === path && sys . flag === flag ) {
47
+ this . systems . splice ( i , 1 , { path, system, flag } ) ;
44
48
return ;
45
49
}
46
50
}
47
- this . systems . push ( { path, system } ) ;
51
+ this . systems . push ( { path, system, flag } ) ;
48
52
this . isOrdered = false ;
49
53
}
50
54
@@ -56,10 +60,11 @@ export class FileSystemAbstraction implements FileSystem {
56
60
* @returns Content of the file
57
61
*/
58
62
read ( filePath : string ) : Promise < Buffer > {
59
- return this . get ( filePath ) . read ( filePath ) ;
63
+ return this . get ( filePath , 'r' ) . read ( filePath ) ;
60
64
}
61
65
62
- /** Read a file as JSON
66
+ /**
67
+ * Read a file as JSON
63
68
* @param filePath file to read
64
69
* @returns JSON Content of the file
65
70
*/
@@ -75,7 +80,7 @@ export class FileSystemAbstraction implements FileSystem {
75
80
* @returns Stream of file contents
76
81
*/
77
82
stream ( filePath : string ) : Readable {
78
- return this . get ( filePath ) . stream ( filePath ) ;
83
+ return this . get ( filePath , 'r' ) . stream ( filePath ) ;
79
84
}
80
85
81
86
/**
@@ -89,9 +94,9 @@ export class FileSystemAbstraction implements FileSystem {
89
94
write ( filePath : string , buffer : FileWriteTypes , opts ?: WriteOptions ) : Promise < void > {
90
95
if ( Array . isArray ( buffer ) || isRecord ( buffer ) ) {
91
96
const content = JSON . stringify ( buffer , null , 2 ) ;
92
- return this . get ( filePath ) . write ( filePath , content , { contentType : 'application/json' , ...opts } ) ;
97
+ return this . get ( filePath , 'rw' ) . write ( filePath , content , { contentType : 'application/json' , ...opts } ) ;
93
98
}
94
- return this . get ( filePath ) . write ( filePath , buffer , opts ) ;
99
+ return this . get ( filePath , 'rw' ) . write ( filePath , buffer , opts ) ;
95
100
}
96
101
97
102
/**
@@ -100,7 +105,7 @@ export class FileSystemAbstraction implements FileSystem {
100
105
* @returns list of files inside that path
101
106
*/
102
107
list ( filePath : string , opts ?: ListOptions ) : AsyncGenerator < string > {
103
- return this . get ( filePath ) . list ( filePath , opts ) ;
108
+ return this . get ( filePath , 'r' ) . list ( filePath , opts ) ;
104
109
}
105
110
106
111
/**
@@ -111,7 +116,7 @@ export class FileSystemAbstraction implements FileSystem {
111
116
* @returns list of files inside that path
112
117
*/
113
118
details ( filePath : string , opts ?: ListOptions ) : AsyncGenerator < FileInfo > {
114
- return this . get ( filePath ) . details ( filePath , opts ) ;
119
+ return this . get ( filePath , 'r' ) . details ( filePath , opts ) ;
115
120
}
116
121
117
122
/**
@@ -121,7 +126,7 @@ export class FileSystemAbstraction implements FileSystem {
121
126
* @returns true if file exists, false otherwise
122
127
*/
123
128
exists ( filePath : string ) : Promise < boolean > {
124
- return this . get ( filePath )
129
+ return this . get ( filePath , 'r' )
125
130
. head ( filePath )
126
131
. then ( ( f ) => f != null ) ;
127
132
}
@@ -133,7 +138,7 @@ export class FileSystemAbstraction implements FileSystem {
133
138
* @returns basic information such as file size
134
139
*/
135
140
head ( filePath : string ) : Promise < FileInfo | null > {
136
- return this . get ( filePath ) . head ( filePath ) ;
141
+ return this . get ( filePath , 'r' ) . head ( filePath ) ;
137
142
}
138
143
139
144
join = joinUri ;
@@ -145,7 +150,7 @@ export class FileSystemAbstraction implements FileSystem {
145
150
* @returns
146
151
*/
147
152
source ( filePath : string ) : ChunkSource {
148
- return this . get ( filePath ) . source ( filePath ) ;
153
+ return this . get ( filePath , 'r' ) . source ( filePath ) ;
149
154
}
150
155
151
156
/**
@@ -160,28 +165,18 @@ export class FileSystemAbstraction implements FileSystem {
160
165
}
161
166
162
167
/** Find the filesystem that would be used for a given path */
163
- get ( filePath : string ) : FileSystem {
168
+ get ( filePath : string , flag : Flag ) : FileSystem {
164
169
this . sortSystems ( ) ;
165
170
for ( const cfg of this . systems ) {
166
- if ( filePath . startsWith ( cfg . path ) ) return cfg . system ;
171
+ if ( filePath . startsWith ( cfg . path ) ) {
172
+ // If we want to write to the system but only have read-only access
173
+ if ( flag === 'rw' && cfg . flag === 'r' ) continue ;
174
+ return cfg . system ;
175
+ }
167
176
}
168
177
169
178
throw new Error ( `Unable to find file system for path:${ filePath } ` ) ;
170
179
}
171
180
}
172
181
173
182
export const fsa = new FileSystemAbstraction ( ) ;
174
-
175
- // async function main(): Promise<void> {
176
- // for await (const f of fsa.list('')) {
177
- // console.log(f);
178
- // }
179
-
180
- // for await (const f of fsa.list('', { details: true })) {
181
- // console.log(f.path);
182
- // }
183
-
184
- // for await (const f of fsa.list('', { details: false, recursive: false })) {
185
- // console.log(f.path);
186
- // }
187
- // }
0 commit comments