@@ -4,11 +4,10 @@ import path from 'path'
4
4
import { argvs , sanitizePackageName , exchangeArgv , execSync , cp , capitalize , regexAll } from './utils' ;
5
5
6
6
import { fileURLToPath } from 'url' ;
7
+ // @ts -expect-error
7
8
const __dirname = path . dirname ( fileURLToPath ( import . meta. url ) ) ;
8
9
9
10
10
-
11
-
12
11
class build {
13
12
14
13
language :string = 'python' ;
@@ -18,12 +17,11 @@ class build {
18
17
destinationFolder :string ;
19
18
downloadAndDelete :boolean ;
20
19
21
- constructor ( exchange : string , downloadAndDelete : boolean ) {
20
+ constructor ( exchange : string ) {
22
21
this . exchange = exchange ;
23
22
this . sourceFolder = __dirname + `/ccxt/` ;
24
23
this . destinationFolder = __dirname + `/../${ exchange } /ccxt/` ;
25
- this . downloadAndDelete = downloadAndDelete ;
26
- this . init ( exchange ) ;
24
+ this . downloadAndDelete = ! argvs . includes ( '--nodownload' ) ;
27
25
}
28
26
29
27
async downloadCcxtRepo ( ) {
@@ -139,54 +137,60 @@ class build {
139
137
fs . writeFileSync ( __dirname + '/../meta.json' , stringified ) ;
140
138
}
141
139
142
- replaceGlobalRegexes ( text : string , array : any [ ] ) {
140
+ replaceGlobalRegexes ( text : string , array : any [ ] = [ ] ) {
143
141
let newText = text ;
144
142
newText = regexAll ( newText , [
145
143
[ '__exchangeName__' , this . exchange ] ,
146
144
[ '__ExchangeName__' , capitalize ( this . exchange ) ] ,
147
145
] ) ;
148
- const otherStrings = {
146
+ const defaults : any = {
149
147
'__LINK_TO_OFFICIAL_EXCHANGE_DOCS__' : 'https://ccxt.com' ,
150
- '__PYTHON_PACKAGE_NAME__' : undefined ,
151
148
'__EXAMPLE_SYMBOL__' : 'BTC/USDC' ,
152
149
} ;
153
150
const exchangeConfig = this . globalConfigs [ 'exchanges' ] [ this . exchange ] ;
154
- for ( const key in otherStrings ) {
155
- const defaultValue = otherStrings [ key ] ;
156
- let value = exchangeConfig [ key ] || defaultValue ; // at first, read from config, if not, use default
151
+ for ( const key in defaults ) {
152
+ const defaultValue = defaults [ key ] ;
153
+ let value = exchangeConfig [ key ] || defaultValue ; // use default if value not set
157
154
newText = newText . replace ( new RegExp ( `${ key } ` , 'g' ) , value ) ;
158
155
}
159
- const sanitized = sanitizePackageName ( exchangeConfig [ '__PYTHON_PACKAGE_NAME__' ] ) ;
160
- newText = newText . replace ( new RegExp ( `__PYTHON_PACKAGE_KEY__` , 'g' ) , sanitized ) ;
156
+ // newText = newText.replace(/__PYTHON_PACKAGE_KEY__/g, sanitizePackageName (exchangeConfig['__PYTHON_PACKAGE_NAME__']));
161
157
return newText ;
162
158
}
163
159
160
+ commonContentReplace ( filePath : string ) {
161
+ let fileContent = fs . readFileSync ( filePath , 'utf8' ) ;
162
+ fileContent = this . replaceGlobalRegexes ( fileContent ) ;
163
+ fs . writeFileSync ( filePath , fileContent ) ;
164
+ }
165
+
164
166
generateExamples ( ) {
165
167
const destinationDir = __dirname + `/../examples/` ;
166
168
cp ( __dirname + '/templates/examples/' , destinationDir ) ;
167
169
// iterate through files and make replacements
168
170
const files = fs . readdirSync ( destinationDir ) ;
169
171
for ( const file of files ) {
170
- const filePath = destinationDir + file ;
171
- let fileContent = fs . readFileSync ( filePath , 'utf8' ) ;
172
- fileContent = this . replaceGlobalRegexes ( fileContent , [ ] ) ;
173
- fs . writeFileSync ( filePath , fileContent ) ;
172
+ this . commonContentReplace ( destinationDir + file ) ;
174
173
}
175
174
}
176
175
177
176
generateReadme ( ) {
178
- const destinationDir = __dirname + `/../README.md` ;
179
- cp ( __dirname + '/templates/README.md' , destinationDir ) ;
180
- let fileContent = fs . readFileSync ( destinationDir , 'utf8' ) ;
181
- fileContent = this . replaceGlobalRegexes ( fileContent , [ ] ) ;
182
- fs . writeFileSync ( destinationDir , fileContent ) ;
177
+ const target = __dirname + `/../README.md` ;
178
+ cp ( __dirname + '/templates/README.md' , target ) ;
179
+ this . commonContentReplace ( target ) ;
180
+ this . updateReadmeWithMethods ( )
183
181
}
184
182
185
- async init ( exchange :string ) {
183
+ generatePyprojectToml ( ) {
184
+ const target = __dirname + `/../pyproject.toml` ;
185
+ cp ( __dirname + '/templates/pyproject.toml' , target ) ;
186
+ this . commonContentReplace ( target ) ;
187
+ }
188
+
189
+ async init ( ) {
186
190
if ( this . downloadAndDelete ) {
187
191
await this . downloadCcxtRepo ( ) ;
188
192
}
189
- this . copyCcxtFiles ( exchange ) ;
193
+ this . copyCcxtFiles ( this . exchange ) ;
190
194
await this . setAllExchangesList ( ) ;
191
195
await this . creataPackageInitFile ( ) ;
192
196
@@ -204,12 +208,110 @@ class build {
204
208
}
205
209
console . log ( "Done!" ) ;
206
210
}
211
+
212
+
213
+
214
+ sortMethods ( methods : string [ ] ) {
215
+ return methods . sort ( ( a , b ) => {
216
+ const aPriority = a . startsWith ( 'fetch' ) || a . startsWith ( 'create' ) ? 0 : 1 ;
217
+ const bPriority = b . startsWith ( 'fetch' ) || b . startsWith ( 'create' ) ? 0 : 1 ;
218
+ return aPriority - bPriority || a . localeCompare ( b ) ;
219
+ } ) ;
220
+ }
221
+
222
+
223
+ updateReadme ( methods : string [ ] , rawMethods : string [ ] , wsMethods : string [ ] , readmePath : string ) {
224
+ let readmeContent = fs . readFileSync ( readmePath , 'utf8' ) ;
225
+
226
+ const methodsFormatted = methods . map ( method => `- \`${ method } \`` ) . join ( '\n' ) ;
227
+ const rawMethodsFormatted = rawMethods . map ( method => `- \`${ method } \`` ) . join ( '\n' ) ;
228
+ const wsMethodsFormatted = wsMethods . map ( method => `- \`${ method } \`` ) . join ( '\n' ) ;
229
+
230
+ const newMethodsSection = `### REST Unified\n\n${ methodsFormatted } \n` ;
231
+
232
+ const newWsMethodsSection = `### WS Unified\n\n${ wsMethodsFormatted } \n` ;
233
+
234
+ const newRawMethodsSection = `### REST Raw\n\n${ rawMethodsFormatted } \n` ;
235
+
236
+ // Replace the existing #Methods section
237
+ const regex = / # # # R E S T U n i f i e d \n [ \s \S ] * ?(? = \n # | $ ) / ;
238
+ if ( regex . test ( readmeContent ) ) {
239
+ readmeContent = readmeContent . replace ( regex , newMethodsSection ) ;
240
+ } else {
241
+ readmeContent += `\n${ newMethodsSection } ` ;
242
+ }
243
+
244
+ // handleRestRaw
245
+ const rawMethodRegex = / # # # R E S T R a w \n [ \s \S ] * ?(? = \n # | $ ) /
246
+ if ( rawMethodRegex . test ( readmeContent ) ) {
247
+ readmeContent = readmeContent . replace ( rawMethodRegex , newRawMethodsSection ) ;
248
+ } else {
249
+ readmeContent += `\n${ newRawMethodsSection } ` ;
250
+ }
251
+
252
+ // handleWs
253
+ const wsRegex = / # # # W S U n i f i e d \n [ \s \S ] * ?(? = \n # | $ ) / ;
254
+ if ( wsRegex . test ( readmeContent ) ) {
255
+ readmeContent = readmeContent . replace ( wsRegex , newWsMethodsSection ) ;
256
+ } else {
257
+ readmeContent += `\n${ newWsMethodsSection } ` ;
258
+ }
259
+
260
+ fs . writeFileSync ( readmePath , readmeContent , 'utf8' ) ;
261
+ }
262
+
263
+ async updateReadmeWithMethods ( ) {
264
+ const filePath = this . destinationFolder + '/' + this . exchange + '.py' ;
265
+ const wsFilePath = this . destinationFolder + '/pro/' + this . exchange + '.py' ;
266
+ const abstractFile = this . destinationFolder + '/abstract/' + this . exchange + '.py' ;
267
+ const readme = __dirname + '/../README.md' ;
268
+
269
+
270
+ const content = fs . readFileSync ( filePath , 'utf8' ) ;
271
+ const wsContent = fs . readFileSync ( wsFilePath , 'utf8' ) ;
272
+ const abstractContent = fs . readFileSync ( abstractFile , 'utf8' ) ;
273
+ const methodRegex = / d e f \s + ( [ a - z A - Z _ ] [ a - z A - Z 0 - 9 _ ] * ) \( ( [ ^ ) ] * ) \) / g;
274
+ const abstractRegex = / \s + ( \w + ) \s = \s \w + \s = \s / g
275
+ let restMethods : string [ ] = [ ] ;
276
+ let wsMethods : string [ ] = [ ] ;
277
+ let rawMethods : string [ ] = [ ] ;
278
+ let match ;
279
+
280
+ while ( ( match = methodRegex . exec ( content ) ) !== null ) {
281
+ const name = match [ 1 ] ;
282
+ if ( name . startsWith ( 'parse' ) || name . startsWith ( 'sign' ) || name . startsWith ( 'handle' ) || name . startsWith ( 'load' ) ) {
283
+ continue ;
284
+ }
285
+ restMethods . push ( `${ name } (${ match [ 2 ] } )` ) ;
286
+ }
287
+
288
+ while ( ( match = methodRegex . exec ( wsContent ) ) !== null ) {
289
+ const name = match [ 1 ] ;
290
+ if ( name . startsWith ( 'handle' ) || name . startsWith ( 'parse' ) || name . startsWith ( 'request' ) || name . startsWith ( 'ping' ) ) {
291
+ continue ;
292
+ }
293
+ wsMethods . push ( `${ name } (${ match [ 2 ] } )` ) ;
294
+ }
295
+
296
+ while ( ( match = abstractRegex . exec ( abstractContent ) ) !== null ) {
297
+ const name = match [ 1 ] ;
298
+ rawMethods . push ( `${ name } (request)` ) ;
299
+ }
300
+
301
+
302
+ // console.log(this.sortMethods(re))
303
+ this . updateReadme ( this . sortMethods ( restMethods ) , rawMethods , wsMethods , readme ) ;
304
+ return restMethods ;
305
+ }
207
306
}
208
307
209
308
210
309
// -------------------------------------------------------------------------------- //
211
310
212
311
213
-
214
- const donwloadAndDelete = ! argvs . includes ( '--nodownload' ) ;
215
- new build ( exchangeArgv , donwloadAndDelete ) ;
312
+ const builder = new build ( exchangeArgv ) ;
313
+ if ( argvs [ 1 ] === '--methods' ) {
314
+ builder . updateReadmeWithMethods ( )
315
+ } else {
316
+ builder . init ( )
317
+ }
0 commit comments