4
4
import * as p from "@clack/prompts" ;
5
5
import path from "path" ;
6
6
import fs from "fs" ;
7
+ import os from "os" ;
7
8
import { fileURLToPath } from "url" ;
8
9
import { exec } from "child_process" ;
9
10
import { promisify } from "util" ;
@@ -78,10 +79,15 @@ async function updatePackageJson(projectName) {
78
79
) ;
79
80
}
80
81
81
- async function updateRescriptJson ( projectName ) {
82
+ async function updateRescriptJson ( projectName , sourceDir ) {
82
83
await updateFile ( "rescript.json" , contents => {
83
84
const config = JSON . parse ( contents ) ;
84
85
config [ "name" ] = projectName ;
86
+
87
+ if ( sourceDir ) {
88
+ config [ "sources" ] [ "dir" ] = sourceDir ;
89
+ }
90
+
85
91
return JSON . stringify ( config , null , 2 ) ;
86
92
} ) ;
87
93
}
@@ -96,18 +102,94 @@ function getVersion() {
96
102
return JSON . parse ( contents ) . version ;
97
103
}
98
104
99
- async function main ( ) {
100
- console . clear ( ) ;
105
+ function getProjectPackageJson ( ) {
106
+ const packageJsonPath = path . join ( process . cwd ( ) , "package.json" ) ;
107
+ const contents = fs . readFileSync ( packageJsonPath , "utf8" ) ;
108
+ return JSON . parse ( contents ) ;
109
+ }
101
110
102
- p . intro ( c . dim ( "create-rescript-app " + getVersion ( ) ) ) ;
111
+ async function addToExistingProject ( ) {
112
+ const projectName = getProjectPackageJson ( ) . name ;
103
113
104
- p . note (
105
- `${ c . cyan ( "Fast, Simple, Fully Typed JavaScript from the Future" ) }
106
- https://www.rescript-lang.org\n\nCreate a new ReScript 11 project with modern defaults
107
- ("Core" standard library, JSX 4 automatic mode)` ,
108
- "Welcome to ReScript!"
109
- ) ;
114
+ const templatePath = path . join ( __dirname , "templates" , "rescript-template-basic" ) ;
115
+ const projectPath = process . cwd ( ) ;
116
+ const gitignorePath = path . join ( projectPath , ".gitignore" ) ;
117
+
118
+ const s = p . spinner ( ) ;
119
+
120
+ try {
121
+ const addToProj = await p . confirm ( {
122
+ message : `Detected a package.json file. Do you want to add ReScript to "${ projectName } "?` ,
123
+ } ) ;
124
+ checkCancel ( addToProj ) ;
125
+
126
+ s . start ( "Loading available versions..." ) ;
127
+ const [ rescriptVersions , rescriptCoreVersions ] = await Promise . all ( [
128
+ getPackageVersions ( "rescript" , rescriptVersionRange ) ,
129
+ getPackageVersions ( "@rescript/core" , rescriptCoreVersionRange ) ,
130
+ ] ) ;
131
+ s . stop ( "Versions loaded." ) ;
110
132
133
+ const rescriptVersion = await p . select ( {
134
+ message : "ReScript version?" ,
135
+ options : rescriptVersions . map ( v => ( { value : v } ) ) ,
136
+ } ) ;
137
+ checkCancel ( rescriptVersion ) ;
138
+
139
+ const rescriptCoreVersion = await p . select ( {
140
+ message : "ReScript Core version?" ,
141
+ options : rescriptCoreVersions . map ( v => ( { value : v } ) ) ,
142
+ } ) ;
143
+ checkCancel ( rescriptCoreVersion ) ;
144
+
145
+ const sourceDir = await p . text ( {
146
+ message : "Where will you put your ReScript source files?" ,
147
+ defaultValue : "src" ,
148
+ placeholder : "src" ,
149
+ initialValue : "src" ,
150
+ } ) ;
151
+ checkCancel ( sourceDir ) ;
152
+
153
+ await fs . promises . copyFile (
154
+ path . join ( templatePath , "rescript.json" ) ,
155
+ path . join ( projectPath , "rescript.json" )
156
+ ) ;
157
+
158
+ if ( fs . existsSync ( gitignorePath ) ) {
159
+ await fs . promises . appendFile ( gitignorePath , "/lib/" + os . EOL + ".bsb.lock" + os . EOL ) ;
160
+ }
161
+
162
+ await updateRescriptJson ( projectName , sourceDir ) ;
163
+
164
+ const sourceDirPath = path . join ( projectPath , sourceDir ) ;
165
+
166
+ if ( ! fs . existsSync ( sourceDirPath ) ) {
167
+ fs . mkdirSync ( sourceDirPath ) ;
168
+ }
169
+
170
+ await fs . promises . copyFile (
171
+ path . join ( templatePath , "src" , "Demo.res" ) ,
172
+ path . join ( sourceDirPath , "Demo.res" )
173
+ ) ;
174
+
175
+ const packages = [ `rescript@${ rescriptVersion } ` , `@rescript/core@${ rescriptCoreVersion } ` ] ;
176
+
177
+ await promisify ( exec ) ( "npm add " + packages . join ( " " ) ) ;
178
+
179
+ s . stop ( "Added ReScript to your project." ) ;
180
+ p . note ( `cd ${ projectName } \nnpm run res:dev` , "Next steps" ) ;
181
+ p . outro ( `Happy hacking!` ) ;
182
+ } catch ( error ) {
183
+ console . warn ( error ) ;
184
+ s . stop ( "Installation error." ) ;
185
+
186
+ p . outro ( `Adding ReScript to project failed.` ) ;
187
+
188
+ p . log . error ( error ) ;
189
+ }
190
+ }
191
+
192
+ async function createNewProject ( ) {
111
193
const projectName = await p . text ( {
112
194
message : "What is the name of your new ReScript project?" ,
113
195
placeholder : process . argv [ 2 ] || "my-rescript-app" ,
@@ -176,4 +258,25 @@ Change to the ${c.cyan(projectName)} folder and view ${c.cyan("README.md")} for
176
258
}
177
259
}
178
260
261
+ async function main ( ) {
262
+ console . clear ( ) ;
263
+
264
+ p . intro ( c . dim ( "create-rescript-app " + getVersion ( ) ) ) ;
265
+
266
+ p . note (
267
+ `${ c . cyan ( "Fast, Simple, Fully Typed JavaScript from the Future" ) }
268
+ https://www.rescript-lang.org\n\nCreate a new ReScript 11 project with modern defaults
269
+ ("Core" standard library, JSX 4 automatic mode)` ,
270
+ "Welcome to ReScript!"
271
+ ) ;
272
+
273
+ const existingPackageJson = fs . existsSync ( path . join ( process . cwd ( ) , "package.json" ) ) ;
274
+
275
+ if ( existingPackageJson ) {
276
+ addToExistingProject ( ) ;
277
+ } else {
278
+ createNewProject ( ) ;
279
+ }
280
+ }
281
+
179
282
main ( ) ;
0 commit comments