1
+ import * as path from "node:path" ;
2
+ import { exec } from "node:child_process" ;
3
+ import { promisify } from "node:util" ;
4
+ import fs from "node:fs/promises" ;
5
+
6
+ const execAsync = promisify ( exec ) ;
7
+
8
+ const bins = await import (
9
+ path . join ( import . meta. dirname , "../node_modules/rescript/cli/common/bins.js" )
10
+ ) ;
11
+ const rescriptTools = bins [ "rescript_tools_exe" ] ;
12
+
13
+ if ( ! rescriptTools ) {
14
+ throw new Error ( "rescript-tools not found" ) ;
15
+ }
16
+
17
+ async function getDocJson ( filePath ) {
18
+ try {
19
+ const command = `${ rescriptTools } doc "${ filePath } "` ;
20
+ const options = { maxBuffer : 10 * 1024 * 1024 } ;
21
+ const { stdout, stderr } = await execAsync ( command , options ) ;
22
+
23
+ if ( stderr ) {
24
+ throw new Error ( `Error executing command for ${ filePath } : ${ stderr } ` ) ;
25
+ }
26
+
27
+ return JSON . parse ( stdout ) ;
28
+ } catch ( error ) {
29
+ throw new Error ( `Failed to get documentation JSON for ${ filePath } :` , error ) ;
30
+ }
31
+ }
32
+
33
+ async function processFile ( filePath ) {
34
+ const json = await getDocJson ( filePath ) ;
35
+
36
+ const moduleName = "WebAPI." + json . name . replace ( "-WebAPI" , "" ) ;
37
+
38
+ const types = [ ] ;
39
+ const functions = [ ] ;
40
+
41
+ function mkType ( item ) {
42
+ let description = "" ;
43
+ if ( item . docstrings . length > 0 ) {
44
+ description = "\n Description: " + item . docstrings . join ( "\n" ) ;
45
+ }
46
+ let fields = "" ;
47
+ if ( item . detail && item . detail . kind === "record" ) {
48
+ fields =
49
+ "\n Fields:\n" +
50
+ item . detail . items
51
+ . map ( ( field ) => {
52
+ let fieldDoc = "" ;
53
+ if ( field . docstrings . length > 0 ) {
54
+ fieldDoc = " - " + field . docstrings . join ( " " ) ;
55
+ }
56
+ return ` - ${ field . name } : ${ field . signature } ${ fieldDoc } ` ;
57
+ } )
58
+ . join ( "\n" ) ;
59
+ }
60
+ return `- ${ item . signature } ${ description } ${ fields } ` ;
61
+ }
62
+
63
+ function mkFunction ( item ) {
64
+ let description = "" ;
65
+ if ( item . docstrings . length > 0 ) {
66
+ description = "\n Description: " + item . docstrings . join ( "\n" ) ;
67
+ }
68
+ return `- ${ item . signature } ${ description } ` ;
69
+ }
70
+
71
+ for ( const item of json . items ) {
72
+ switch ( item . kind ) {
73
+ case "type" :
74
+ types . push ( mkType ( item ) ) ;
75
+ break ;
76
+ case "value" :
77
+ functions . push ( mkFunction ( item ) ) ;
78
+ break ;
79
+ }
80
+ }
81
+
82
+ let typeString = "" ;
83
+ if ( types . length > 0 ) {
84
+ typeString = "\n\nTypes:\n\n" + types . join ( "\n\n" ) ;
85
+ }
86
+
87
+ let functionString = "" ;
88
+ if ( functions . length > 0 ) {
89
+ functionString = "\n\nFunctions:\n\n" + functions . join ( "\n\n" ) ;
90
+ }
91
+
92
+ return `File: ${ json . source . filepath }
93
+ Module: ${ moduleName } ${ typeString } ${ functionString }
94
+ ` ;
95
+ }
96
+
97
+ const pattern = "../src/**/*.res"
98
+ const files = [ ] ;
99
+ for await ( const file of fs . glob ( pattern , { recursive : true , cwd : import . meta. dirname } ) ) {
100
+ files . push ( path . join ( import . meta. dirname , file ) ) ;
101
+ }
102
+ files . sort ( ) ;
103
+
104
+ const pages = await Promise . all ( files . map ( processFile ) )
105
+ const packageJson = await fs . readFile ( path . join ( import . meta. dirname , "../package.json" ) , "utf-8" ) ;
106
+ let version = JSON . parse ( packageJson ) . version ;
107
+ const sha = await execAsync ( "git rev-parse --short HEAD" ) . then ( ( { stdout } ) => stdout . trim ( ) ) ;
108
+ const fullVersion = `${ version } -${ sha } ` ;
109
+ const header = `Experimental Rescript WebAPI Documentation ${ fullVersion }
110
+
111
+ This is the API documentation for the experimental WebAPI module version ${ fullVersion } .
112
+ More information can be found on https://rescript-lang.github.io/experimental-rescript-webapi/
113
+
114
+ `
115
+ const content = pages . join ( "\n---\n\n" ) ;
116
+ await fs . writeFile ( path . join ( import . meta. dirname , "public/llm.txt" ) , header + content ) ;
117
+ console . log ( "Generated llm.txt" ) ;
0 commit comments