1+
2+ import { BaseAdaptor , BaseAdaptorOptions } from '../../base' ;
3+ import { FileStat , PathMap } from '../../definitions' ;
4+
5+ export interface MemoryAdaptorOptions extends BaseAdaptorOptions { }
6+
7+ interface MemoryFile extends FileStat {
8+ content ?: string ;
9+ }
10+
11+ interface MemoryStore {
12+ [ path : string ] : MemoryFile ;
13+ }
14+
15+ export class MemoryAdaptor extends BaseAdaptor {
16+ private files : MemoryStore = { } ;
17+
18+ static isSupported ( ) : boolean {
19+ return true ;
20+ }
21+
22+ constructor ( ref : string , options : BaseAdaptorOptions ) {
23+ super ( ref , options ) ;
24+ }
25+
26+ async init ( ) : Promise < void > {
27+ this . isInitialized = true ;
28+ }
29+
30+ async destroy ( ) : Promise < void > {
31+ this . isInitialized = false ;
32+ }
33+
34+ #toStat( file : MemoryFile ) : FileStat {
35+ const stat = { ...file } ;
36+ delete stat . content ;
37+ return stat ;
38+ }
39+
40+ async stat ( path : string ) : Promise < FileStat | null > {
41+ const file = this . files [ path ] ;
42+ if ( ! file ) {
43+ return null ;
44+ }
45+ return this . #toStat( file ) ;
46+ }
47+
48+ async readFile ( path : string ) : Promise < Buffer > {
49+ const file = this . files [ path ] ;
50+ if ( ! file || file . isDirectory ) {
51+ throw new Error ( `File not found: ${ path } ` ) ;
52+ }
53+ return Buffer . from ( file . content || '' , 'base64' ) ;
54+ }
55+
56+ async writeFile ( path : string , data : Buffer ) : Promise < void > {
57+ const file = this . files [ path ] ;
58+ this . files [ path ] = {
59+ path,
60+ parentPath : path . split ( '/' ) . slice ( 0 , - 1 ) . join ( '/' )
61+ . replace ( / ( ^ \/ ) | ( \/ $ ) / g, '' ) ,
62+ isDirectory : false ,
63+ isFile : true ,
64+ size : data . length ,
65+ modifiedTime : new Date ( ) ,
66+ createdTime : file . createdTime || new Date ( ) ,
67+ content : data . toString ( 'base64' ) ,
68+ } ;
69+ }
70+
71+ async deleteFile ( path : string ) : Promise < void > {
72+ delete this . files [ path ] ;
73+ }
74+
75+ async list ( path : string ) : Promise < PathMap > {
76+ const files : PathMap = { } ;
77+ for ( const filePath in this . files ) {
78+ if ( filePath . startsWith ( path + '/' ) ) {
79+ const relativePath = filePath . slice ( path . length + 1 ) ;
80+ const parts = relativePath . split ( '/' ) ;
81+ if ( parts . length === 1 ) {
82+ files [ parts [ 0 ] ] = this . #toStat( this . files [ filePath ] ) ;
83+ } else {
84+ const dirName = parts [ 0 ] ;
85+ if ( ! files [ dirName ] ) {
86+ files [ dirName ] = this . #toStat( this . files [ `${ path } /${ dirName } ` ] ) ;
87+ }
88+ }
89+ }
90+ }
91+ return files ;
92+ }
93+
94+ async mkdir ( path : string ) : Promise < void > {
95+ this . files [ path ] = {
96+ path,
97+ parentPath : path . split ( '/' ) . slice ( 0 , - 1 ) . join ( '/' )
98+ . replace ( / ( ^ \/ ) | ( \/ $ ) / g, '' ) ,
99+ isDirectory : true ,
100+ isFile : false ,
101+ size : 0 ,
102+ modifiedTime : new Date ( ) ,
103+ createdTime : new Date ( ) ,
104+ } ;
105+ }
106+
107+ async rmdir ( path : string ) : Promise < void > {
108+ for ( const filePath in this . files ) {
109+ if ( filePath . startsWith ( path + '/' ) ) {
110+ delete this . files [ filePath ] ;
111+ }
112+ }
113+ delete this . files [ path ] ;
114+ }
115+
116+ async _copyFile ( path : string , targetPath : string , newFileName ?: string ) : Promise < void > {
117+ const file = this . files [ path ] ;
118+ if ( ! file || file . isDirectory ) {
119+ throw new Error ( `File not found: ${ path } ` ) ;
120+ }
121+ const targetFilePath = newFileName ? `${ targetPath } /${ newFileName } ` : `${ targetPath } /${ path . split ( '/' ) . pop ( ) } ` ;
122+ this . files [ targetFilePath ] = {
123+ ...file ,
124+ path : targetFilePath ,
125+ parentPath : targetPath ,
126+ modifiedTime : new Date ( ) ,
127+ createdTime : new Date ( ) ,
128+ } ;
129+ }
130+
131+ async _copyDirectory ( path : string , targetPath : string , recursive ?: boolean ) : Promise < void > {
132+ const files = await this . list ( path ) ;
133+ for ( const fileName in files ) {
134+ const filePath = `${ path } /${ fileName } ` ;
135+ const targetFilePath = `${ targetPath } /${ fileName } ` ;
136+ if ( files [ fileName ] . isDirectory ) {
137+ await this . mkdir ( targetFilePath ) ;
138+ if ( recursive ) {
139+ await this . _copyDirectory ( filePath , targetFilePath , true ) ;
140+ }
141+ } else {
142+ await this . _copyFile ( filePath , targetPath ) ;
143+ }
144+ }
145+ }
146+ }
0 commit comments