-
Notifications
You must be signed in to change notification settings - Fork 215
/
add.ts
135 lines (110 loc) · 3.88 KB
/
add.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
import {color} from '@heroku-cli/color'
import {Command, flags} from '@heroku-cli/command'
import * as Heroku from '@heroku-cli/schema'
import {CliUx} from '@oclif/core'
import Spinner from '@oclif/core/lib/cli-ux/action/spinner'
import {prompt} from 'inquirer'
import * as shellescape from 'shell-escape'
import waitForDomain from '../../lib/wait-for-domain'
const cli = CliUx.ux
interface DomainCreatePayload {
hostname: string;
sni_endpoint: string | null;
}
export default class DomainsAdd extends Command {
static description = 'add a domain to an app'
static examples = ['heroku domains:add www.example.com']
static flags = {
help: flags.help({char: 'h'}),
app: flags.app({required: true}),
cert: flags.string({description: 'the name of the SSL cert you want to use for this domain', char: 'c'}),
json: flags.boolean({description: 'output in json format', char: 'j'}),
wait: flags.boolean(),
remote: flags.remote(),
}
static args = [{name: 'hostname', required: true}]
certSelect = async (certs: Array<Heroku.SniEndpoint>) => {
const nullCertChoice = {
name: 'No SNI Endpoint',
value: null,
}
const certChoices = certs.map((cert: Heroku.SniEndpoint) => {
const certName = cert.displayName || cert.name
const domainsLength = cert.ssl_cert.cert_domains.length
if (domainsLength) {
let domainsList = cert.ssl_cert.cert_domains.slice(0, 4).join(', ')
if (domainsLength > 5) {
domainsList = `${domainsList} (...and ${domainsLength - 4} more)`
}
domainsList = `${certName} -> ${domainsList}`
return {
name: domainsList,
value: cert.name,
}
}
return {
name: certName,
value: cert.name,
}
})
const selection = await prompt<{ cert: string }>([
{
type: 'list',
name: 'cert',
message: 'Choose an SNI endpoint to associate with this domain',
choices: [nullCertChoice, ...certChoices],
},
])
return selection.cert
}
async run() {
const {args, flags} = await this.parse(DomainsAdd)
const {hostname} = args
const action = new Spinner()
const domainCreatePayload: DomainCreatePayload = {
hostname,
sni_endpoint: null,
}
let certs: Array<Heroku.SniEndpoint> = []
action.start(`Adding ${color.green(domainCreatePayload.hostname)} to ${color.app(flags.app)}`)
if (flags.cert) {
domainCreatePayload.sni_endpoint = flags.cert
} else {
const {body} = await this.heroku.get<Array<Heroku.SniEndpoint>>(`/apps/${flags.app}/sni-endpoints`)
certs = [...body]
}
if (certs.length > 1) {
action.stop('resolving SNI endpoint')
const certSelection = await this.certSelect(certs)
if (certSelection) {
domainCreatePayload.sni_endpoint = certSelection
}
action.start(`Adding ${color.green(domainCreatePayload.hostname)} to ${color.app(flags.app)}`)
}
try {
const {body: domain} = await this.heroku.post<Heroku.Domain>(`/apps/${flags.app}/domains`, {
body: domainCreatePayload,
})
if (flags.json) {
cli.styledJSON(domain)
} else {
cli.log(`Configure your app's DNS provider to point to the DNS Target ${color.green(domain.cname || '')}.
For help, see https://devcenter.heroku.com/articles/custom-domains`)
if (domain.status !== 'none') {
if (flags.wait) {
await waitForDomain(flags.app, this.heroku, domain)
} else {
cli.log('')
cli.log(`The domain ${color.green(hostname)} has been enqueued for addition`)
const command = `heroku domains:wait ${shellescape([hostname])}`
cli.log(`Run ${color.cmd(command)} to wait for completion`)
}
}
}
} catch (error: any) {
cli.error(error)
} finally {
action.stop()
}
}
}