@@ -4,11 +4,12 @@ if (parseInt(process.version.split(".")[0], 10) < 10) {
4
4
}
5
5
6
6
const fsp = require ( "fs" ) . promises ;
7
- const { randomBytes } = require ( "crypto" ) ;
8
7
const { spawnSync : rawSpawnSync } = require ( "child_process" ) ;
9
8
const dotenv = require ( "dotenv" ) ;
10
9
const inquirer = require ( "inquirer" ) ;
11
10
const pg = require ( "pg" ) ;
11
+ const { withDotenvUpdater, readDotenv } = require ( "./lib/dotenv" ) ;
12
+ const { safeRandomString } = require ( "./lib/random" ) ;
12
13
13
14
// fixes spawnSync not throwing ENOENT on windows
14
15
const platform = require ( "os" ) . platform ( ) ;
@@ -61,85 +62,7 @@ const spawnSync = (cmd, args, options) => {
61
62
62
63
const sleep = ms => new Promise ( resolve => setTimeout ( resolve , ms ) ) ;
63
64
64
- const DOTENV_PATH = `${ __dirname } /../.env` ;
65
-
66
- function safeRandomString ( length ) {
67
- // Roughly equivalent to shell `openssl rand -base64 30 | tr '+/' '-_'`
68
- return randomBytes ( length )
69
- . toString ( "base64" )
70
- . replace ( / \+ / g, "-" )
71
- . replace ( / \/ / g, "_" ) ;
72
- }
73
-
74
- async function readDotenv ( ) {
75
- let buffer = null ;
76
- try {
77
- buffer = await fsp . readFile ( DOTENV_PATH ) ;
78
- } catch ( e ) {
79
- /* noop */
80
- }
81
- const config = buffer ? dotenv . parse ( buffer ) : null ;
82
- // also read from current env, because docker-compose already needs to know some of it
83
- // eg. $PG_DUMP, $CONFIRM
84
- return { ...config , ...process . env } ;
85
- }
86
-
87
- function encodeDotenvValue ( str ) {
88
- if ( typeof str !== "string" ) {
89
- throw new Error ( `'${ str } ' is not a string` ) ;
90
- }
91
- if ( str . trim ( ) !== str ) {
92
- // `dotenv` would escape this with single/double quotes but that won't work in docker-compose
93
- throw new Error (
94
- "We don't support leading/trailing whitespace in config variables"
95
- ) ;
96
- }
97
- if ( str . indexOf ( "\n" ) >= 0 ) {
98
- // `dotenv` would escape this with single/double quotes and `\n` but that won't work in docker-compose
99
- throw new Error ( "We don't support newlines in config variables" ) ;
100
- }
101
- return str ;
102
- }
103
-
104
- async function updateDotenv ( answers ) {
105
- let data ;
106
- try {
107
- data = await fsp . readFile ( DOTENV_PATH , "utf8" ) ;
108
- // Trim whitespace, and prefix with newline so we can do easier checking later
109
- data = "\n" + data . trim ( ) ;
110
- } catch ( e ) {
111
- data = "" ;
112
- }
113
-
114
- function add ( varName , defaultValue , comment ) {
115
- const SET = `\n${ varName } =` ;
116
- const encodedValue = encodeDotenvValue (
117
- varName in answers ? answers [ varName ] : defaultValue || ""
118
- ) ;
119
- const pos = data . indexOf ( SET ) ;
120
- if ( pos >= 0 ) {
121
- /* Replace this value with the new value */
122
-
123
- // Where's the next newline (or the end of the file if there is none)
124
- let nlpos = data . indexOf ( "\n" , pos + 1 ) ;
125
- if ( nlpos < 0 ) {
126
- nlpos = data . length ;
127
- }
128
-
129
- // Surgical editing
130
- data =
131
- data . substr ( 0 , pos + SET . length ) + encodedValue + data . substr ( nlpos ) ;
132
- } else {
133
- /* This value didn't already exist; add it to the end */
134
-
135
- if ( comment ) {
136
- data += `\n\n${ comment } ` ;
137
- }
138
-
139
- data += `${ SET } ${ encodedValue } ` ;
140
- }
141
- }
142
-
65
+ function updateDotenv ( add , answers ) {
143
66
add (
144
67
"GRAPHILE_LICENSE" ,
145
68
null ,
@@ -262,10 +185,6 @@ async function updateDotenv(answers) {
262
185
# The name of the folder you cloned graphile-starter to (so we can run docker-compose inside a container):`
263
186
) ;
264
187
}
265
-
266
- data = data . trim ( ) + "\n" ;
267
-
268
- await fsp . writeFile ( DOTENV_PATH , data ) ;
269
188
}
270
189
271
190
async function main ( ) {
@@ -335,10 +254,12 @@ async function main() {
335
254
] ;
336
255
const answers = await inquirer . prompt ( questions ) ;
337
256
338
- await updateDotenv ( {
339
- ...config ,
340
- ...answers ,
341
- } ) ;
257
+ await withDotenvUpdater ( answers , add =>
258
+ updateDotenv ( add , {
259
+ ...config ,
260
+ ...answers ,
261
+ } )
262
+ ) ;
342
263
343
264
// And perform setup
344
265
spawnSync ( yarnCmd , [ "server" , "build" ] ) ;
@@ -397,9 +318,14 @@ async function main() {
397
318
await pgPool . query ( 'select true as "Connection test";' ) ;
398
319
break ;
399
320
} catch ( e ) {
321
+ if ( e . code === "28P01" ) {
322
+ throw e ;
323
+ }
400
324
attempts ++ ;
401
325
if ( attempts <= 30 ) {
402
- console . log ( `Database is not ready yet (attempt ${ attempts } )` ) ;
326
+ console . log (
327
+ `Database is not ready yet (attempt ${ attempts } ): ${ e . message } `
328
+ ) ;
403
329
} else {
404
330
console . log ( `Database never came up, aborting :(` ) ;
405
331
process . exit ( 1 ) ;
0 commit comments