6
6
from typing import Any , TextIO
7
7
8
8
import yaml
9
- from camel_converter import to_pascal
10
9
11
10
12
11
def ind (n : int ) -> str :
13
12
return n * 4 * ' '
14
13
15
14
15
+ def doc_wrap (s : str , indent : int ) -> str :
16
+ s = s .strip ()
17
+ if '\n ' in s :
18
+ return f'\n { ind (indent )} ' .join (doc_wrap (c , indent ) for c in s .split ('\n ' ))
19
+
20
+ max_length = 120 - indent * 4 - 3
21
+ result = ''
22
+ while True :
23
+ if len (s ) < max_length :
24
+ result += ' * ' + s
25
+ break
26
+ pos = 0
27
+ while True :
28
+ next = s .find (' ' , pos + 1 )
29
+ if next < 0 or next >= max_length :
30
+ break
31
+ pos = next
32
+ result += ' * ' + s [:pos ] + '\n ' + ind (indent )
33
+ s = s [pos + 1 :]
34
+ return result
35
+
36
+
37
+ def html_to_doc (s : str ) -> str :
38
+ s = (s .replace ('<code>' , '``' )
39
+ .replace ('</code>' , '``' )
40
+ .replace ('<br>' , '\\ \n ' )
41
+ .replace ('<i>' , '*' )
42
+ .replace ('</i>' , '*' )
43
+ .replace ('<b>' , '**' )
44
+ .replace ('</b>' , '**' )
45
+ .replace ('<ul>' , '\n ' )
46
+ .replace ('<li>' , '* ' )
47
+ .replace ('</li>' , '' )
48
+ .replace ('</ul>' , '' ))
49
+ s = re .sub (r'<a [^>]*>' , '' , s )
50
+ s = s .replace ('</a>' , '' )
51
+ return s
52
+
53
+
16
54
def read_api (ifname : str ) -> Any :
17
55
with open (ifname , 'r' ) as ifile :
18
56
return yaml .safe_load (ifile )
@@ -114,7 +152,9 @@ def generate_operations(operations: Any, tfile: TextIO, sfile: TextIO) -> None:
114
152
tfile .write ('\n ' )
115
153
tfile .write (f'export interface { operations ["name" ]} {{\n ' )
116
154
for field in operations ['fields' ]:
117
- tfile .write (f' { field ["name" ]} ?: PrincipalValue | null;\n ' )
155
+ if 'description' in field :
156
+ tfile .write (f'{ ind (1 )} /**\n { ind (1 )} * { field ["description" ]} \n { ind (1 )} */\n ' )
157
+ tfile .write (f'{ ind (1 )} { field ["name" ]} ?: PrincipalValue | null;\n ' )
118
158
tfile .write ('}\n ' )
119
159
120
160
sfile .write ('\n ' )
@@ -276,6 +316,10 @@ def generate_class(self, tfile: TextIO, structs: dict[str, Structure]) -> None:
276
316
t = to_js_type (field ['type' ])
277
317
if field .get ('array' , False ):
278
318
t += '[]'
319
+ if 'description' in field :
320
+ tfile .write (f'{ ind (1 )} /**\n ' )
321
+ tfile .write (ind (1 ) + doc_wrap (html_to_doc (field ["description" ]), 1 ))
322
+ tfile .write (f'\n { ind (1 )} */\n ' )
279
323
tfile .write (tmpl % (field ['name' ], t ))
280
324
tfile .write ('}\n ' )
281
325
if self .generic :
@@ -406,7 +450,8 @@ def generate_calls(api: Any, structs: dict[str, Structure], afile: TextIO) -> No
406
450
url_params : dict [str , str ] = {}
407
451
flag_name : str | None = None
408
452
flag_js_name : str | None = None
409
- flags : list [str ] = []
453
+ flags : list [Any ] = []
454
+ param_docs = []
410
455
for param in request .get ('params' , []) + request .get ('query' , []):
411
456
if 'name' not in param :
412
457
print ('Missing name of parameter of the request "{method} {url}"'
@@ -422,23 +467,28 @@ def generate_calls(api: Any, structs: dict[str, Structure], afile: TextIO) -> No
422
467
if 'flags' in param :
423
468
flag_name = name
424
469
flag_js_name = js_name
425
- flags = [flag [ 'name' ] for flag in param ['flags' ]]
470
+ flags = [flag for flag in param ['flags' ]]
426
471
for flag in flags :
427
- params .append ('with{name}: boolean = false' .format (name = flag .capitalize ()))
472
+ flag_param = f'with{ flag ["name" ].capitalize ()} '
473
+ params .append (f'{ flag_param } : boolean = false' )
474
+ param_docs += [(flag_param , 'include ' + flag .get ('description' , '' ), 'boolean' )]
428
475
else :
429
476
if param .get ('optional' , False ):
430
477
tail_params .append (f'{ js_name } : { js_type } | null = null' )
478
+ param_docs += [(js_name , param .get ('description' , '' ), f'{ js_type } | null' )]
431
479
else :
432
480
params .append (f'{ js_name } : { js_type } ' )
481
+ param_docs += [(js_name , param .get ('description' , '' ), js_type )]
433
482
body = ''
434
483
if 'in' in request :
435
484
if 'type' in request ['in' ]:
436
485
if request ['in' ]['type' ] != 'blob' :
437
486
print ('Unrecognised type "{type}" of the input body of the request "{method} {url}"'
438
487
.format (type = request ['in' ]['type' ], method = request ['type' ], url = request ['url' ]))
439
488
exit (1 )
440
- body = ', body'
441
- params .append ('body: Buffer' )
489
+ body = ', body, contentType'
490
+ params += ['body: Buffer' , 'contentType: string' ]
491
+ param_docs += [('body' , '' , 'Buffer' ), ('contentType' , 'content-type of ``body``' , 'string' )]
442
492
else :
443
493
if 'name' not in request ['in' ]:
444
494
print ('Missing name of body of the request "{method} {url}"'
@@ -450,6 +500,7 @@ def generate_calls(api: Any, structs: dict[str, Structure], afile: TextIO) -> No
450
500
js_type += '[]'
451
501
body = f', body: { name } '
452
502
params .append (f'{ name } : { js_type } ' )
503
+ param_docs += [(name , request ['in' ].get ('description' , '' ), js_type )]
453
504
params += tail_params
454
505
455
506
method = request ['type' ]
@@ -494,10 +545,24 @@ def generate_calls(api: Any, structs: dict[str, Structure], afile: TextIO) -> No
494
545
result += '[]'
495
546
result_schema += 'Array'
496
547
548
+ description = ''
549
+ if 'description' in request :
550
+ description = doc_wrap (html_to_doc (request ["description" ]), 1 )
551
+ description += f'\n { ind (1 )} *'
552
+ if len (param_docs ) > 0 :
553
+ for pd in param_docs :
554
+ param_doc = ' - ' + html_to_doc (pd [1 ]) if pd [1 ] != '' else ''
555
+ doc = doc_wrap (f'@param {{{ pd [2 ]} }} { pd [0 ]} { param_doc } ' , 1 )
556
+ description += f'\n { ind (1 )} { doc } '
557
+ description += f'\n { ind (1 )} ' + doc_wrap (f'@return {{Promise<{ result } >}}' , 1 )
558
+ if description != '' :
559
+ description = f'\n { ind (1 )} /**\n { ind (1 )} { description } \n { ind (1 )} */'
560
+
561
+ afile .write (description )
497
562
name = request ['function' ]
498
563
afile .write (params_wrap (f'\n { ind (1 )} async { name } (%s): Promise<{ result } > {{\n ' , ', ' .join (params ), 2 ))
499
564
if flag_name is not None :
500
- items = ', ' .join ('"%s": with%s' % (flag , flag .capitalize ()) for flag in flags )
565
+ items = ', ' .join ('"%s": with%s' % (flag [ 'name' ] , flag [ 'name' ] .capitalize ()) for flag in flags )
501
566
afile .write (f'{ ind (2 )} const { flag_js_name } = commaSeparatedFlags({{{ items } }});\n ' )
502
567
afile .write (f'{ ind (2 )} const location = { location } ;\n ' )
503
568
query_params = ''
@@ -533,8 +598,14 @@ def generate_calls(api: Any, structs: dict[str, Structure], afile: TextIO) -> No
533
598
import * as API from "./types";
534
599
import { commaSeparatedFlags, ut } from "../util";
535
600
601
+ /**
602
+ * Node API interface.
603
+ */
536
604
export class MoeraNode extends Caller {
537
605
606
+ /**
607
+ * @param {string | null} nodeUrl - the node URL
608
+ */
538
609
constructor(nodeUrl: string | null = null) {
539
610
super();
540
611
if (nodeUrl != null) {
0 commit comments