@@ -12,14 +12,19 @@ type SerializeContent<I> = (content: I) => string;
1212type DeserializeContent = ( content : string ) => unknown ;
1313type GetFileName = ( id : string ) => string ;
1414
15- export type UserDataOptions < Input > = {
15+ export type FileUserDataOptions < Input > = {
1616 subdir : string ;
1717 basePath ?: string ;
1818 serialize ?: SerializeContent < Input > ;
1919 deserialize ?: DeserializeContent ;
2020 getFileName ?: GetFileName ;
2121} ;
2222
23+ export type AtlasUserDataOptions < Input > = {
24+ serialize ?: SerializeContent < Input > ;
25+ deserialize ?: DeserializeContent ;
26+ } ;
27+
2328type ReadOptions = {
2429 ignoreErrors : boolean ;
2530} ;
@@ -63,28 +68,54 @@ export interface ReadAllWithStatsResult<T extends z.Schema> {
6368 errors : Error [ ] ;
6469}
6570
66- export class UserData < T extends z . Schema > {
71+ export abstract class IUserData < T extends z . Schema > {
72+ protected readonly validator : T ;
73+ protected readonly serialize : SerializeContent < z . input < T > > ;
74+ protected readonly deserialize : DeserializeContent ;
75+
76+ constructor (
77+ validator : T ,
78+ {
79+ serialize = ( content : z . input < T > ) => JSON . stringify ( content , null , 2 ) ,
80+ deserialize = JSON . parse ,
81+ } : {
82+ serialize ?: SerializeContent < z . input < T > > ;
83+ deserialize ?: DeserializeContent ;
84+ } = { }
85+ ) {
86+ this . validator = validator ;
87+ this . serialize = serialize ;
88+ this . deserialize = deserialize ;
89+ }
90+
91+ abstract write ( id : string , content : z . input < T > ) : Promise < boolean > ;
92+ abstract delete ( id : string ) : Promise < boolean > ;
93+ abstract readAll ( options ?: ReadOptions ) : Promise < ReadAllResult < T > > ;
94+ abstract updateAttributes (
95+ id : string ,
96+ data : Partial < z . input < T > >
97+ ) : Promise < z . output < T > > ;
98+ }
99+
100+ export class FileUserData < T extends z . Schema > extends IUserData < T > {
67101 private readonly subdir : string ;
68102 private readonly basePath ?: string ;
69- private readonly serialize : SerializeContent < z . input < T > > ;
70- private readonly deserialize : DeserializeContent ;
71103 private readonly getFileName : GetFileName ;
72- private readonly semaphore = new Semaphore ( 100 ) ;
104+ protected readonly semaphore = new Semaphore ( 100 ) ;
73105
74106 constructor (
75- private readonly validator : T ,
107+ validator : T ,
76108 {
77109 subdir,
78110 basePath,
79- serialize = ( content : z . input < T > ) => JSON . stringify ( content , null , 2 ) ,
80- deserialize = JSON . parse ,
111+ serialize,
112+ deserialize,
81113 getFileName = ( id ) => `${ id } .json` ,
82- } : UserDataOptions < z . input < T > >
114+ } : FileUserDataOptions < z . input < T > >
83115 ) {
116+ super ( validator , { serialize, deserialize } ) ;
84117 this . subdir = subdir ;
85118 this . basePath = basePath ;
86- this . deserialize = deserialize ;
87- this . serialize = serialize ;
88119 this . getFileName = getFileName ;
89120 }
90121
@@ -290,4 +321,15 @@ export class UserData<T extends z.Schema> {
290321 ) {
291322 return ( await this . readOneWithStats ( id , options ) ) ?. [ 0 ] ;
292323 }
324+
325+ async updateAttributes (
326+ id : string ,
327+ data : Partial < z . input < T > >
328+ ) : Promise < z . output < T > > {
329+ await this . write ( id , {
330+ ...( ( await this . readOne ( id ) ) ?? { } ) ,
331+ ...data ,
332+ } ) ;
333+ return await this . readOne ( id ) ;
334+ }
293335}
0 commit comments