1
- import { OptionValues } from 'commander'
2
- import inquirer from 'inquirer'
3
1
import BaseCommand from '../base-command.js'
4
- import { getAccount , getExtension , getSiteConfiguration , installExtension } from './utils.js'
5
- import { initDrizzle } from './drizzle.js'
6
- import { NEON_DATABASE_EXTENSION_SLUG } from './constants.js'
7
- import prettyjson from 'prettyjson'
8
- import { chalk , log } from '../../utils/command-helpers.js'
2
+ import { status } from './status.js'
3
+ import { init } from './init.js'
9
4
10
- type SiteInfo = {
5
+ export type Extension = {
6
+ id : string
7
+ name : string
8
+ slug : string
9
+ hostSiteUrl : string
10
+ installedOnTeam : boolean
11
+ }
12
+
13
+ export type SiteInfo = {
11
14
id : string
12
15
name : string
13
16
account_id : string
@@ -16,224 +19,13 @@ type SiteInfo = {
16
19
ssl_url : string
17
20
}
18
21
19
- const init = async ( _options : OptionValues , command : BaseCommand ) => {
20
- const siteInfo = command . netlify . siteInfo as SiteInfo
21
- if ( ! command . siteId ) {
22
- console . error ( `The project must be linked with netlify link before initializing a database.` )
23
- return
24
- }
25
-
26
- const initialOpts = command . opts ( )
27
-
28
- /**
29
- * Only prompt for drizzle if the user did not pass in the `--drizzle` or `--no-drizzle` option
30
- */
31
- if ( initialOpts . drizzle !== false && initialOpts . drizzle !== true && ! initialOpts . yes ) {
32
- type Answers = {
33
- drizzle : boolean
34
- }
35
- const answers = await inquirer . prompt < Answers > ( [
36
- {
37
- type : 'confirm' ,
38
- name : 'drizzle' ,
39
- message : 'Use Drizzle?' ,
40
- } ,
41
- ] )
42
- command . setOptionValue ( 'drizzle' , answers . drizzle )
43
- }
44
-
45
- const opts = command . opts < {
46
- drizzle ?: boolean | undefined
47
- /**
48
- * Skip prompts and use default values (answer yes to all prompts)
49
- */
50
- yes ?: true | undefined
51
- } > ( )
52
-
53
- if ( opts . drizzle || ( opts . yes && opts . drizzle !== false ) ) {
54
- await initDrizzle ( command )
55
- }
56
-
57
- if ( ! command . netlify . api . accessToken ) {
58
- throw new Error ( `Please login with netlify login before running this command` )
59
- }
60
-
61
- if ( ! siteInfo . account_id || ! siteInfo . name ) {
62
- throw new Error ( `Error getting site, make sure you are logged in with netlify login` )
63
- }
64
-
65
- const account = await getAccount ( command , { accountId : siteInfo . account_id } )
66
-
67
- log ( `Initializing a new database...` )
68
-
69
- const netlifyToken = command . netlify . api . accessToken . replace ( 'Bearer ' , '' )
70
- const extension = await getExtension ( {
71
- accountId : siteInfo . account_id ,
72
- token : netlifyToken ,
73
- slug : NEON_DATABASE_EXTENSION_SLUG ,
74
- } )
75
- if ( ! extension ?. hostSiteUrl ) {
76
- throw new Error ( `Failed to get extension host site url when installing extension` )
77
- }
78
-
79
- const installNeonExtension = async ( ) => {
80
- if ( ! siteInfo . account_id || ! account . name ) {
81
- throw new Error ( `Failed to install extension "${ extension . name } "` )
82
- }
83
- const installed = await installExtension ( {
84
- accountId : siteInfo . account_id ,
85
- token : netlifyToken ,
86
- slug : NEON_DATABASE_EXTENSION_SLUG ,
87
- hostSiteUrl : extension . hostSiteUrl ,
88
- } )
89
- if ( ! installed ) {
90
- throw new Error ( `Failed to install extension on team "${ account . name } ": "${ extension . name } "` )
91
- }
92
- log ( `Extension "${ extension . name } " successfully installed on team "${ account . name } "` )
93
- }
94
-
95
- if ( ! extension . installedOnTeam && ! opts . yes ) {
96
- type Answers = {
97
- installExtension : boolean
98
- }
99
- const answers = await inquirer . prompt < Answers > ( [
100
- {
101
- type : 'confirm' ,
102
- name : 'installExtension' ,
103
- message : `The required extension "${ extension . name } " is not installed on team "${ account . name } ", would you like to install it now?` ,
104
- } ,
105
- ] )
106
- if ( answers . installExtension ) {
107
- await installNeonExtension ( )
108
- } else {
109
- return
110
- }
111
- }
112
- if ( ! extension . installedOnTeam && opts . yes ) {
113
- await installNeonExtension ( )
114
- }
115
-
116
- try {
117
- const siteEnv = await command . netlify . api . getEnvVar ( {
118
- accountId : siteInfo . account_id ,
119
- siteId : command . siteId ,
120
- key : 'NETLIFY_DATABASE_URL' ,
121
- } )
122
-
123
- if ( siteEnv . key === 'NETLIFY_DATABASE_URL' ) {
124
- log ( `Environment variable "NETLIFY_DATABASE_URL" already exists on site: ${ siteInfo . name } ` )
125
- log ( `You can run "netlify db status" to check the status for this site` )
126
- return
127
- }
128
- } catch {
129
- // no op, env var does not exist, so we just continue
130
- }
131
-
132
- const hostSiteUrl = process . env . NEON_DATABASE_EXTENSION_HOST_SITE_URL ?? extension . hostSiteUrl
133
- const initEndpoint = new URL ( '/cli-db-init' , hostSiteUrl ) . toString ( )
134
-
135
- const req = await fetch ( initEndpoint , {
136
- method : 'POST' ,
137
- headers : {
138
- 'Content-Type' : 'application/json' ,
139
- 'nf-db-token' : netlifyToken ,
140
- 'nf-db-site-id' : command . siteId ,
141
- 'nf-db-account-id' : siteInfo . account_id ,
142
- } ,
143
- } )
144
-
145
- if ( ! req . ok ) {
146
- throw new Error ( `Failed to initialize DB: ${ await req . text ( ) } ` )
147
- }
148
-
149
- const res = ( await req . json ( ) ) as {
150
- code ?: string
151
- message ?: string
152
- }
153
- if ( res . code === 'DATABASE_INITIALIZED' ) {
154
- if ( res . message ) {
155
- log ( res . message )
156
- }
157
-
158
- log (
159
- prettyjson . render ( {
160
- 'Current team' : account . name ,
161
- 'Current site' : siteInfo . name ,
162
- [ `${ extension . name } extension` ] : 'installed' ,
163
- Database : 'connected' ,
164
- 'Site environment variable' : 'NETLIFY_DATABASE_URL' ,
165
- } ) ,
166
- )
167
- }
168
- return
169
- }
170
-
171
- const status = async ( _options : OptionValues , command : BaseCommand ) => {
172
- const siteInfo = command . netlify . siteInfo as SiteInfo
173
- if ( ! command . siteId ) {
174
- throw new Error ( `The project must be linked with netlify link before initializing a database.` )
175
- }
176
- if ( ! siteInfo . account_id ) {
177
- throw new Error ( `No account id found for site ${ command . siteId } ` )
178
- }
179
- if ( ! command . netlify . api . accessToken ) {
180
- throw new Error ( `You must be logged in with netlify login to check the status of the database` )
181
- }
182
- const netlifyToken = command . netlify . api . accessToken . replace ( 'Bearer ' , '' )
183
-
184
- const account = await getAccount ( command , { accountId : siteInfo . account_id } )
185
-
186
- let siteEnv : Awaited < ReturnType < typeof command . netlify . api . getEnvVar > > | undefined
187
- try {
188
- siteEnv = await command . netlify . api . getEnvVar ( {
189
- accountId : siteInfo . account_id ,
190
- siteId : command . siteId ,
191
- key : 'NETLIFY_DATABASE_URL' ,
192
- } )
193
- } catch {
194
- // no-op, env var does not exist, so we just continue
195
- }
196
-
197
- const extension = await getExtension ( {
198
- accountId : account . id ,
199
- token : netlifyToken ,
200
- slug : NEON_DATABASE_EXTENSION_SLUG ,
201
- } )
202
- let siteConfig
203
- try {
204
- siteConfig = await getSiteConfiguration ( {
205
- siteId : command . siteId ,
206
- accountId : siteInfo . account_id ,
207
- slug : NEON_DATABASE_EXTENSION_SLUG ,
208
- token : netlifyToken ,
209
- } )
210
- } catch {
211
- // no-op, site config does not exist or extension not installed
212
- }
213
-
214
- log (
215
- prettyjson . render ( {
216
- 'Current team' : account . name ,
217
- 'Current site' : siteInfo . name ,
218
- [ extension ?. name ? `${ extension . name } extension` : 'Database extension' ] : extension ?. installedOnTeam
219
- ? 'installed'
220
- : chalk . red ( 'not installed' ) ,
221
- // @ts -expect-error -- siteConfig is not typed
222
- // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
223
- Database : siteConfig ?. config ?. neonProjectId ? 'connected' : chalk . red ( 'not connected' ) ,
224
- 'Site environment variable' :
225
- siteEnv ?. key === 'NETLIFY_DATABASE_URL' ? 'NETLIFY_DATABASE_URL' : chalk . red ( 'NETLIFY_DATABASE_URL not set' ) ,
226
- } ) ,
227
- )
228
- }
229
-
230
22
export const createDatabaseCommand = ( program : BaseCommand ) => {
231
23
const dbCommand = program . command ( 'db' ) . alias ( 'database' ) . description ( `TODO: write description for database command` )
232
24
233
25
dbCommand
234
26
. command ( 'init' )
235
27
. description ( 'Initialize a new database' )
236
- . option ( ' --drizzle' , 'Sets up drizzle-kit and drizzle-orm in your project ' )
28
+ . option ( ` --drizzle` , 'Initialize basic drizzle config and schema boilerplate ' )
237
29
. option ( '--no-drizzle' , 'Skips drizzle' )
238
30
. option ( '-y, --yes' , 'Skip prompts and use default values' )
239
31
. option ( '-o, --overwrite' , 'Overwrites existing files that would be created when setting up drizzle' )
0 commit comments