1
+ const DatabaseError = require ( "./Error" ) ;
2
+ const Path = require ( "path" ) ;
3
+ const { existsSync, mkdirSync, writeFileSync, readFileSync, unlinkSync } = require ( "fs" ) ;
4
+ const { set, get, unset } = require ( "lodash" ) ;
5
+
6
+ class Database {
7
+
8
+ constructor ( { path = "databases/database.json" } = { } ) {
9
+
10
+ path = path . replaceAll ( "/" , Path . sep ) . replaceAll ( "\\" , Path . sep )
11
+ let basePath = process . cwd ( ) ;
12
+ if ( path . startsWith ( basePath ) ) {
13
+ path = path . replace ( basePath , "" ) ;
14
+ }
15
+
16
+ if ( path . startsWith ( `.${ Path . sep } ` ) ) {
17
+ path = path . slice ( 1 ) ;
18
+ }
19
+
20
+ if ( ! path . startsWith ( Path . sep ) ) {
21
+ path = Path . sep + path ;
22
+ }
23
+
24
+ if ( ! path . endsWith ( ".json" ) ) {
25
+ if ( path . endsWith ( Path . sep ) ) {
26
+ path += "database.json" ;
27
+ } else {
28
+ path += ".json" ;
29
+ }
30
+ }
31
+
32
+ basePath = `${ basePath } ${ path } ` ;
33
+
34
+ const dirNames = path . split ( Path . sep ) . slice ( 1 ) ;
35
+
36
+ const length = dirNames . length ;
37
+
38
+ if ( length > 1 ) {
39
+ dirNames . pop ( ) ;
40
+
41
+ const firstResolvedDir = Path . resolve ( dirNames [ 0 ] ) ;
42
+
43
+ if ( ! existsSync ( firstResolvedDir ) ) {
44
+ mkdirSync ( firstResolvedDir ) ;
45
+ }
46
+
47
+ dirNames . splice ( 0 , 1 ) ;
48
+
49
+ let targetDirPath = firstResolvedDir ;
50
+
51
+ for ( const dirName of dirNames ) {
52
+ const currentPath = `${ targetDirPath } ${ Path . sep } ${ dirName } ` ;
53
+
54
+ if ( ! existsSync ( currentPath ) ) {
55
+ mkdirSync ( currentPath ) ;
56
+ }
57
+
58
+ targetDirPath = `${ targetDirPath } ${ Path . sep } ${ dirName } ` ;
59
+ }
60
+ }
61
+
62
+ this . path = basePath ;
63
+
64
+ if ( ! existsSync ( this . path ) ) {
65
+ writeFileSync ( this . path , "{}" ) ;
66
+ }
67
+ }
68
+
69
+ set ( key , value ) {
70
+ if ( key === "" || typeof key !== "string" ) {
71
+ throw new DatabaseError ( "Please Specify String For Key" ) ;
72
+ }
73
+
74
+ if (
75
+ value === "" ||
76
+ value === undefined ||
77
+ value === null
78
+ ) {
79
+ throw new DatabaseError ( "Please Specify String For Value" ) ;
80
+ }
81
+
82
+ const jsonData = this . toJSON ( ) ;
83
+
84
+ set ( jsonData , key , value ) ;
85
+
86
+ writeFileSync ( this . path , JSON . stringify ( jsonData , null , 4 ) ) ;
87
+
88
+ return value ;
89
+ }
90
+
91
+ get ( key ) {
92
+ if ( key === "" || typeof key !== "string" ) {
93
+ throw new DatabaseError ( "Please Specify String For Key" ) ;
94
+ }
95
+
96
+ const jsonData = this . toJSON ( ) ;
97
+
98
+ const data = get ( jsonData , key ) ;
99
+ return data ;
100
+ }
101
+
102
+ has ( key ) {
103
+ if ( key === "" || typeof key !== "string" ) {
104
+ throw new DatabaseError ( "Please Specify String For Key" ) ;
105
+ }
106
+
107
+ return this . toJSON ( ) . hasOwnProperty ( key ) ;
108
+ }
109
+
110
+ all ( limit = 0 ) {
111
+ if ( typeof limit !== "number" ) {
112
+ throw new DatabaseError ( "Please Specify Number For Limit" ) ;
113
+ }
114
+
115
+ const jsonData = JSON . parse ( readFileSync ( this . path , "utf-8" ) ) ;
116
+
117
+ const arr = [ ] ;
118
+ for ( const key in jsonData ) {
119
+ arr . push ( {
120
+ ID : key ,
121
+ data : jsonData [ key ]
122
+ } ) ;
123
+ }
124
+
125
+ return limit > 0 ? arr . splice ( 0 , limit ) : arr ;
126
+ }
127
+
128
+ toJSON ( limit ) {
129
+ const allData = this . all ( limit ) ;
130
+
131
+ const json = { } ;
132
+ for ( const element of allData ) {
133
+ json [ element . ID ] = element . data ;
134
+ }
135
+ return json ;
136
+ }
137
+
138
+ delete ( key ) {
139
+ if ( key === "" || typeof key !== "string" ) {
140
+ throw new DatabaseError ( "Please Specify String For Key" ) ;
141
+ }
142
+
143
+ const jsonData = this . toJSON ( ) ;
144
+
145
+ unset ( jsonData , key ) ;
146
+
147
+ writeFileSync ( this . path , JSON . stringify ( jsonData , null , 4 ) ) ;
148
+
149
+ return ;
150
+ }
151
+
152
+ clear ( ) {
153
+ writeFileSync ( this . path , "{}" ) ;
154
+ return ;
155
+ }
156
+
157
+ type ( key ) {
158
+ if ( key === "" || typeof key !== "string" ) {
159
+ throw new DatabaseError ( "Please Specify String For Key" ) ;
160
+ }
161
+
162
+ const data = this . get ( key ) ;
163
+
164
+ if ( Array . isArray ( data ) ) return "array" ;
165
+
166
+ else return typeof data ;
167
+ }
168
+
169
+ add ( key , value ) {
170
+ if ( key === "" || typeof key !== "string" ) {
171
+ throw new DatabaseError ( "Please Specify String For Key" ) ;
172
+ }
173
+
174
+ if ( Array . isArray ( value ) || isNaN ( value ) ) {
175
+ throw new DatabaseError ( "Please Specify Number For Value" ) ;
176
+ }
177
+
178
+ if ( value <= 0 ) {
179
+ throw new DatabaseError ( "Please Specify Number Higher Than 0 For Value" ) ;
180
+ }
181
+
182
+ value = Number ( value )
183
+
184
+ let data = this . get ( key ) ;
185
+ if ( ! data ) {
186
+ return this . set ( key , value ) ;
187
+ }
188
+
189
+ if ( Array . isArray ( data ) || isNaN ( data ) ) throw new DatabaseError ( `${ key } ID data is not a number type data.` ) ;
190
+
191
+ data = Number ( data ) ;
192
+
193
+ data += value ;
194
+
195
+ return this . set ( key , data ) ;
196
+ }
197
+
198
+ substr ( key , value , goToNegative ) {
199
+ if ( key === "" || typeof key !== "string" ) {
200
+ throw new DatabaseError ( "Please Specify String For Key" ) ;
201
+ }
202
+
203
+ if ( Array . isArray ( value ) || isNaN ( value ) ) {
204
+ throw new DatabaseError ( "Please Specify Number For Value" ) ;
205
+ }
206
+
207
+ if ( value <= 0 ) {
208
+ throw new DatabaseError ( "Please Specify Number Higher Than 0 For Value" ) ;
209
+ }
210
+
211
+ value = Number ( value )
212
+
213
+ let data = this . get ( key ) ;
214
+ if ( ! data ) {
215
+ return this . set ( key , value ) ;
216
+ }
217
+
218
+ if ( Array . isArray ( data ) || isNaN ( data ) ) throw new DatabaseError ( `${ key } ID data is not a number type data.` ) ;
219
+
220
+ data = Number ( data ) ;
221
+
222
+ data -= value ;
223
+
224
+ return this . set ( key , data ) ;
225
+ }
226
+
227
+ includes ( key ) {
228
+ return this . filter ( ( element ) => element . ID . includes ( key ) ) ;
229
+ }
230
+
231
+ startsWith ( key ) {
232
+ return this . filter ( ( element ) => element . ID . startsWith ( key ) ) ;
233
+ }
234
+
235
+ endsWith ( key ) {
236
+ return this . filter ( ( element ) => element . ID . endsWith ( key ) ) ;
237
+ }
238
+
239
+ filter ( callbackfn , thisArg ) {
240
+ if ( thisArg ) callbackfn = callbackfn . bind ( thisArg ) ;
241
+ return this . all ( ) . filter ( callbackfn ) ;
242
+ }
243
+ }
244
+
245
+ module . exports = Database ;
0 commit comments